Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mattst88...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / amd / powerplay / smumgr / vega10_smumgr.c
1 /*
2  * Copyright 2016 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 #include "smumgr.h"
25 #include "vega10_inc.h"
26 #include "pp_soc15.h"
27 #include "vega10_smumgr.h"
28 #include "vega10_ppsmc.h"
29 #include "smu9_driver_if.h"
30
31 #include "ppatomctrl.h"
32 #include "pp_debug.h"
33 #include "smu_ucode_xfer_vi.h"
34 #include "smu7_smumgr.h"
35
36 #define AVFS_EN_MSB             1568
37 #define AVFS_EN_LSB             1568
38
39 #define VOLTAGE_SCALE   4
40
41 /* Microcode file is stored in this buffer */
42 #define BUFFER_SIZE                 80000
43 #define MAX_STRING_SIZE             15
44 #define BUFFER_SIZETWO              131072 /* 128 *1024 */
45
46 /* MP Apertures */
47 #define MP0_Public                  0x03800000
48 #define MP0_SRAM                    0x03900000
49 #define MP1_Public                  0x03b00000
50 #define MP1_SRAM                    0x03c00004
51
52 #define smnMP1_FIRMWARE_FLAGS                                                                           0x3010028
53 #define smnMP0_FW_INTF                                                                                  0x3010104
54 #define smnMP1_PUB_CTRL                                                                                 0x3010b14
55
56 static bool vega10_is_smc_ram_running(struct pp_smumgr *smumgr)
57 {
58         uint32_t mp1_fw_flags, reg;
59
60         reg = soc15_get_register_offset(NBIF_HWID, 0,
61                         mmPCIE_INDEX2_BASE_IDX, mmPCIE_INDEX2);
62
63         cgs_write_register(smumgr->device, reg,
64                         (MP1_Public | (smnMP1_FIRMWARE_FLAGS & 0xffffffff)));
65
66         reg = soc15_get_register_offset(NBIF_HWID, 0,
67                         mmPCIE_DATA2_BASE_IDX, mmPCIE_DATA2);
68
69         mp1_fw_flags = cgs_read_register(smumgr->device, reg);
70
71         if (mp1_fw_flags & MP1_FIRMWARE_FLAGS__INTERRUPTS_ENABLED_MASK)
72                 return true;
73
74         return false;
75 }
76
77 /*
78  * Check if SMC has responded to previous message.
79  *
80  * @param    smumgr  the address of the powerplay hardware manager.
81  * @return   TRUE    SMC has responded, FALSE otherwise.
82  */
83 static uint32_t vega10_wait_for_response(struct pp_smumgr *smumgr)
84 {
85         uint32_t reg;
86
87         if (!vega10_is_smc_ram_running(smumgr))
88                 return -EINVAL;
89
90         reg = soc15_get_register_offset(MP1_HWID, 0,
91                         mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
92
93         smum_wait_for_register_unequal(smumgr, reg,
94                         0, MP1_C2PMSG_90__CONTENT_MASK);
95
96         return cgs_read_register(smumgr->device, reg);
97 }
98
99 /*
100  * Send a message to the SMC, and do not wait for its response.
101  * @param    smumgr  the address of the powerplay hardware manager.
102  * @param    msg the message to send.
103  * @return   Always return 0.
104  */
105 int vega10_send_msg_to_smc_without_waiting(struct pp_smumgr *smumgr,
106                 uint16_t msg)
107 {
108         uint32_t reg;
109
110         if (!vega10_is_smc_ram_running(smumgr))
111                 return -EINVAL;
112
113         reg = soc15_get_register_offset(MP1_HWID, 0,
114                         mmMP1_SMN_C2PMSG_66_BASE_IDX, mmMP1_SMN_C2PMSG_66);
115         cgs_write_register(smumgr->device, reg, msg);
116
117         return 0;
118 }
119
120 /*
121  * Send a message to the SMC, and wait for its response.
122  * @param    smumgr  the address of the powerplay hardware manager.
123  * @param    msg the message to send.
124  * @return   Always return 0.
125  */
126 int vega10_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg)
127 {
128         uint32_t reg;
129
130         if (!vega10_is_smc_ram_running(smumgr))
131                 return -EINVAL;
132
133         vega10_wait_for_response(smumgr);
134
135         reg = soc15_get_register_offset(MP1_HWID, 0,
136                         mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
137         cgs_write_register(smumgr->device, reg, 0);
138
139         vega10_send_msg_to_smc_without_waiting(smumgr, msg);
140
141         if (vega10_wait_for_response(smumgr) != 1)
142                 pr_err("Failed to send message: 0x%x\n", msg);
143
144         return 0;
145 }
146
147 /*
148  * Send a message to the SMC with parameter
149  * @param    smumgr:  the address of the powerplay hardware manager.
150  * @param    msg: the message to send.
151  * @param    parameter: the parameter to send
152  * @return   Always return 0.
153  */
154 int vega10_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr,
155                 uint16_t msg, uint32_t parameter)
156 {
157         uint32_t reg;
158
159         if (!vega10_is_smc_ram_running(smumgr))
160                 return -EINVAL;
161
162         vega10_wait_for_response(smumgr);
163
164         reg = soc15_get_register_offset(MP1_HWID, 0,
165                         mmMP1_SMN_C2PMSG_90_BASE_IDX, mmMP1_SMN_C2PMSG_90);
166         cgs_write_register(smumgr->device, reg, 0);
167
168         reg = soc15_get_register_offset(MP1_HWID, 0,
169                         mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
170         cgs_write_register(smumgr->device, reg, parameter);
171
172         vega10_send_msg_to_smc_without_waiting(smumgr, msg);
173
174         if (vega10_wait_for_response(smumgr) != 1)
175                 pr_err("Failed to send message: 0x%x\n", msg);
176
177         return 0;
178 }
179
180
181 /*
182  * Send a message to the SMC with parameter, do not wait for response
183  * @param    smumgr:  the address of the powerplay hardware manager.
184  * @param    msg: the message to send.
185  * @param    parameter: the parameter to send
186  * @return   The response that came from the SMC.
187  */
188 int vega10_send_msg_to_smc_with_parameter_without_waiting(
189                 struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter)
190 {
191         uint32_t reg;
192
193         reg = soc15_get_register_offset(MP1_HWID, 0,
194                         mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
195         cgs_write_register(smumgr->device, reg, parameter);
196
197         return vega10_send_msg_to_smc_without_waiting(smumgr, msg);
198 }
199
200 /*
201  * Retrieve an argument from SMC.
202  * @param    smumgr  the address of the powerplay hardware manager.
203  * @param    arg     pointer to store the argument from SMC.
204  * @return   Always return 0.
205  */
206 int vega10_read_arg_from_smc(struct pp_smumgr *smumgr, uint32_t *arg)
207 {
208         uint32_t reg;
209
210         reg = soc15_get_register_offset(MP1_HWID, 0,
211                         mmMP1_SMN_C2PMSG_82_BASE_IDX, mmMP1_SMN_C2PMSG_82);
212
213         *arg = cgs_read_register(smumgr->device, reg);
214
215         return 0;
216 }
217
218 /*
219  * Copy table from SMC into driver FB
220  * @param   smumgr    the address of the SMC manager
221  * @param   table_id    the driver's table ID to copy from
222  */
223 int vega10_copy_table_from_smc(struct pp_smumgr *smumgr,
224                 uint8_t *table, int16_t table_id)
225 {
226         struct vega10_smumgr *priv =
227                         (struct vega10_smumgr *)(smumgr->backend);
228
229         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
230                         "Invalid SMU Table ID!", return -EINVAL);
231         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
232                         "Invalid SMU Table version!", return -EINVAL);
233         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
234                         "Invalid SMU Table Length!", return -EINVAL);
235         PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
236                         PPSMC_MSG_SetDriverDramAddrHigh,
237                         priv->smu_tables.entry[table_id].table_addr_high) == 0,
238                         "[CopyTableFromSMC] Attempt to Set Dram Addr High Failed!", return -EINVAL);
239         PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
240                         PPSMC_MSG_SetDriverDramAddrLow,
241                         priv->smu_tables.entry[table_id].table_addr_low) == 0,
242                         "[CopyTableFromSMC] Attempt to Set Dram Addr Low Failed!",
243                         return -EINVAL);
244         PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
245                         PPSMC_MSG_TransferTableSmu2Dram,
246                         priv->smu_tables.entry[table_id].table_id) == 0,
247                         "[CopyTableFromSMC] Attempt to Transfer Table From SMU Failed!",
248                         return -EINVAL);
249
250         memcpy(table, priv->smu_tables.entry[table_id].table,
251                         priv->smu_tables.entry[table_id].size);
252
253         return 0;
254 }
255
256 /*
257  * Copy table from Driver FB into SMC
258  * @param   smumgr    the address of the SMC manager
259  * @param   table_id    the table to copy from
260  */
261 int vega10_copy_table_to_smc(struct pp_smumgr *smumgr,
262                 uint8_t *table, int16_t table_id)
263 {
264         struct vega10_smumgr *priv =
265                         (struct vega10_smumgr *)(smumgr->backend);
266
267         PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
268                         "Invalid SMU Table ID!", return -EINVAL);
269         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
270                         "Invalid SMU Table version!", return -EINVAL);
271         PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
272                         "Invalid SMU Table Length!", return -EINVAL);
273
274         memcpy(priv->smu_tables.entry[table_id].table, table,
275                         priv->smu_tables.entry[table_id].size);
276
277         PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
278                         PPSMC_MSG_SetDriverDramAddrHigh,
279                         priv->smu_tables.entry[table_id].table_addr_high) == 0,
280                         "[CopyTableToSMC] Attempt to Set Dram Addr High Failed!",
281                         return -EINVAL;);
282         PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
283                         PPSMC_MSG_SetDriverDramAddrLow,
284                         priv->smu_tables.entry[table_id].table_addr_low) == 0,
285                         "[CopyTableToSMC] Attempt to Set Dram Addr Low Failed!",
286                         return -EINVAL);
287         PP_ASSERT_WITH_CODE(vega10_send_msg_to_smc_with_parameter(smumgr,
288                         PPSMC_MSG_TransferTableDram2Smu,
289                         priv->smu_tables.entry[table_id].table_id) == 0,
290                         "[CopyTableToSMC] Attempt to Transfer Table To SMU Failed!",
291                         return -EINVAL);
292
293         return 0;
294 }
295
296 int vega10_save_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table)
297 {
298         PP_ASSERT_WITH_CODE(avfs_table,
299                         "No access to SMC AVFS Table",
300                         return -EINVAL);
301
302         return vega10_copy_table_from_smc(smumgr, avfs_table, AVFSTABLE);
303 }
304
305 int vega10_restore_vft_table(struct pp_smumgr *smumgr, uint8_t *avfs_table)
306 {
307         PP_ASSERT_WITH_CODE(avfs_table,
308                         "No access to SMC AVFS Table",
309                         return -EINVAL);
310
311         return vega10_copy_table_to_smc(smumgr, avfs_table, AVFSTABLE);
312 }
313
314 int vega10_enable_smc_features(struct pp_smumgr *smumgr,
315                 bool enable, uint32_t feature_mask)
316 {
317         int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
318                         PPSMC_MSG_DisableSmuFeatures;
319
320         return vega10_send_msg_to_smc_with_parameter(smumgr,
321                         msg, feature_mask);
322 }
323
324 int vega10_get_smc_features(struct pp_smumgr *smumgr,
325                 uint32_t *features_enabled)
326 {
327         if (features_enabled == NULL)
328                 return -EINVAL;
329
330         if (!vega10_send_msg_to_smc(smumgr,
331                         PPSMC_MSG_GetEnabledSmuFeatures)) {
332                 vega10_read_arg_from_smc(smumgr, features_enabled);
333                 return 0;
334         }
335
336         return -EINVAL;
337 }
338
339 int vega10_set_tools_address(struct pp_smumgr *smumgr)
340 {
341         struct vega10_smumgr *priv =
342                         (struct vega10_smumgr *)(smumgr->backend);
343
344         if (priv->smu_tables.entry[TOOLSTABLE].table_addr_high ||
345                         priv->smu_tables.entry[TOOLSTABLE].table_addr_low) {
346                 if (!vega10_send_msg_to_smc_with_parameter(smumgr,
347                                 PPSMC_MSG_SetToolsDramAddrHigh,
348                                 priv->smu_tables.entry[TOOLSTABLE].table_addr_high))
349                         vega10_send_msg_to_smc_with_parameter(smumgr,
350                                         PPSMC_MSG_SetToolsDramAddrLow,
351                                         priv->smu_tables.entry[TOOLSTABLE].table_addr_low);
352         }
353         return 0;
354 }
355
356 static int vega10_verify_smc_interface(struct pp_smumgr *smumgr)
357 {
358         uint32_t smc_driver_if_version;
359         struct cgs_system_info sys_info = {0};
360         uint32_t dev_id;
361         uint32_t rev_id;
362
363         PP_ASSERT_WITH_CODE(!vega10_send_msg_to_smc(smumgr,
364                         PPSMC_MSG_GetDriverIfVersion),
365                         "Attempt to get SMC IF Version Number Failed!",
366                         return -EINVAL);
367         vega10_read_arg_from_smc(smumgr, &smc_driver_if_version);
368
369         sys_info.size = sizeof(struct cgs_system_info);
370         sys_info.info_id = CGS_SYSTEM_INFO_PCIE_DEV;
371         cgs_query_system_info(smumgr->device, &sys_info);
372         dev_id = (uint32_t)sys_info.value;
373
374         sys_info.size = sizeof(struct cgs_system_info);
375         sys_info.info_id = CGS_SYSTEM_INFO_PCIE_REV;
376         cgs_query_system_info(smumgr->device, &sys_info);
377         rev_id = (uint32_t)sys_info.value;
378
379         if (!((dev_id == 0x687f) &&
380                 ((rev_id == 0xc0) ||
381                 (rev_id == 0xc1) ||
382                 (rev_id == 0xc3)))) {
383                 if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
384                         pr_err("Your firmware(0x%x) doesn't match \
385                                 SMU9_DRIVER_IF_VERSION(0x%x). \
386                                 Please update your firmware!\n",
387                                 smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
388                         return -EINVAL;
389                 }
390         }
391
392         return 0;
393 }
394
395 static int vega10_smu_init(struct pp_smumgr *smumgr)
396 {
397         struct vega10_smumgr *priv;
398         uint64_t mc_addr;
399         void *kaddr = NULL;
400         unsigned long handle, tools_size;
401         int ret;
402         struct cgs_firmware_info info = {0};
403
404         ret = cgs_get_firmware_info(smumgr->device,
405                                     smu7_convert_fw_type_to_cgs(UCODE_ID_SMU),
406                                     &info);
407         if (ret || !info.kptr)
408                 return -EINVAL;
409
410         priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
411
412         if (!priv)
413                 return -ENOMEM;
414
415         smumgr->backend = priv;
416
417         /* allocate space for pptable */
418         smu_allocate_memory(smumgr->device,
419                         sizeof(PPTable_t),
420                         CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
421                         PAGE_SIZE,
422                         &mc_addr,
423                         &kaddr,
424                         &handle);
425
426         PP_ASSERT_WITH_CODE(kaddr,
427                         "[vega10_smu_init] Out of memory for pptable.",
428                         kfree(smumgr->backend);
429                         cgs_free_gpu_mem(smumgr->device,
430                         (cgs_handle_t)handle);
431                         return -EINVAL);
432
433         priv->smu_tables.entry[PPTABLE].version = 0x01;
434         priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
435         priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
436         priv->smu_tables.entry[PPTABLE].table_addr_high =
437                         smu_upper_32_bits(mc_addr);
438         priv->smu_tables.entry[PPTABLE].table_addr_low =
439                         smu_lower_32_bits(mc_addr);
440         priv->smu_tables.entry[PPTABLE].table = kaddr;
441         priv->smu_tables.entry[PPTABLE].handle = handle;
442
443         /* allocate space for watermarks table */
444         smu_allocate_memory(smumgr->device,
445                         sizeof(Watermarks_t),
446                         CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
447                         PAGE_SIZE,
448                         &mc_addr,
449                         &kaddr,
450                         &handle);
451
452         PP_ASSERT_WITH_CODE(kaddr,
453                         "[vega10_smu_init] Out of memory for wmtable.",
454                         kfree(smumgr->backend);
455                         cgs_free_gpu_mem(smumgr->device,
456                         (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
457                         cgs_free_gpu_mem(smumgr->device,
458                         (cgs_handle_t)handle);
459                         return -EINVAL);
460
461         priv->smu_tables.entry[WMTABLE].version = 0x01;
462         priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
463         priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
464         priv->smu_tables.entry[WMTABLE].table_addr_high =
465                         smu_upper_32_bits(mc_addr);
466         priv->smu_tables.entry[WMTABLE].table_addr_low =
467                         smu_lower_32_bits(mc_addr);
468         priv->smu_tables.entry[WMTABLE].table = kaddr;
469         priv->smu_tables.entry[WMTABLE].handle = handle;
470
471         /* allocate space for AVFS table */
472         smu_allocate_memory(smumgr->device,
473                         sizeof(AvfsTable_t),
474                         CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
475                         PAGE_SIZE,
476                         &mc_addr,
477                         &kaddr,
478                         &handle);
479
480         PP_ASSERT_WITH_CODE(kaddr,
481                         "[vega10_smu_init] Out of memory for avfs table.",
482                         kfree(smumgr->backend);
483                         cgs_free_gpu_mem(smumgr->device,
484                         (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
485                         cgs_free_gpu_mem(smumgr->device,
486                         (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
487                         cgs_free_gpu_mem(smumgr->device,
488                         (cgs_handle_t)handle);
489                         return -EINVAL);
490
491         priv->smu_tables.entry[AVFSTABLE].version = 0x01;
492         priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
493         priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
494         priv->smu_tables.entry[AVFSTABLE].table_addr_high =
495                         smu_upper_32_bits(mc_addr);
496         priv->smu_tables.entry[AVFSTABLE].table_addr_low =
497                         smu_lower_32_bits(mc_addr);
498         priv->smu_tables.entry[AVFSTABLE].table = kaddr;
499         priv->smu_tables.entry[AVFSTABLE].handle = handle;
500
501         tools_size = 0x19000;
502         if (tools_size) {
503                 smu_allocate_memory(smumgr->device,
504                                 tools_size,
505                                 CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
506                                 PAGE_SIZE,
507                                 &mc_addr,
508                                 &kaddr,
509                                 &handle);
510
511                 if (kaddr) {
512                         priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
513                         priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
514                         priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
515                         priv->smu_tables.entry[TOOLSTABLE].table_addr_high =
516                                         smu_upper_32_bits(mc_addr);
517                         priv->smu_tables.entry[TOOLSTABLE].table_addr_low =
518                                         smu_lower_32_bits(mc_addr);
519                         priv->smu_tables.entry[TOOLSTABLE].table = kaddr;
520                         priv->smu_tables.entry[TOOLSTABLE].handle = handle;
521                 }
522         }
523
524         /* allocate space for AVFS Fuse table */
525         smu_allocate_memory(smumgr->device,
526                         sizeof(AvfsFuseOverride_t),
527                         CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB,
528                         PAGE_SIZE,
529                         &mc_addr,
530                         &kaddr,
531                         &handle);
532
533         PP_ASSERT_WITH_CODE(kaddr,
534                         "[vega10_smu_init] Out of memory for avfs fuse table.",
535                         kfree(smumgr->backend);
536                         cgs_free_gpu_mem(smumgr->device,
537                         (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
538                         cgs_free_gpu_mem(smumgr->device,
539                         (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
540                         cgs_free_gpu_mem(smumgr->device,
541                         (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
542                         cgs_free_gpu_mem(smumgr->device,
543                         (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
544                         cgs_free_gpu_mem(smumgr->device,
545                         (cgs_handle_t)handle);
546                         return -EINVAL);
547
548         priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
549         priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
550         priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
551         priv->smu_tables.entry[AVFSFUSETABLE].table_addr_high =
552                         smu_upper_32_bits(mc_addr);
553         priv->smu_tables.entry[AVFSFUSETABLE].table_addr_low =
554                         smu_lower_32_bits(mc_addr);
555         priv->smu_tables.entry[AVFSFUSETABLE].table = kaddr;
556         priv->smu_tables.entry[AVFSFUSETABLE].handle = handle;
557
558         return 0;
559 }
560
561 static int vega10_smu_fini(struct pp_smumgr *smumgr)
562 {
563         struct vega10_smumgr *priv =
564                         (struct vega10_smumgr *)(smumgr->backend);
565
566         if (priv) {
567                 cgs_free_gpu_mem(smumgr->device,
568                                 (cgs_handle_t)priv->smu_tables.entry[PPTABLE].handle);
569                 cgs_free_gpu_mem(smumgr->device,
570                                 (cgs_handle_t)priv->smu_tables.entry[WMTABLE].handle);
571                 cgs_free_gpu_mem(smumgr->device,
572                                 (cgs_handle_t)priv->smu_tables.entry[AVFSTABLE].handle);
573                 if (priv->smu_tables.entry[TOOLSTABLE].table)
574                         cgs_free_gpu_mem(smumgr->device,
575                                         (cgs_handle_t)priv->smu_tables.entry[TOOLSTABLE].handle);
576                 cgs_free_gpu_mem(smumgr->device,
577                                 (cgs_handle_t)priv->smu_tables.entry[AVFSFUSETABLE].handle);
578                 kfree(smumgr->backend);
579                 smumgr->backend = NULL;
580         }
581         return 0;
582 }
583
584 static int vega10_start_smu(struct pp_smumgr *smumgr)
585 {
586         PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(smumgr),
587                         "Failed to verify SMC interface!",
588                         return -EINVAL);
589
590         vega10_set_tools_address(smumgr);
591
592         return 0;
593 }
594
595 const struct pp_smumgr_func vega10_smu_funcs = {
596         .smu_init = &vega10_smu_init,
597         .smu_fini = &vega10_smu_fini,
598         .start_smu = &vega10_start_smu,
599         .request_smu_load_specific_fw = NULL,
600         .send_msg_to_smc = &vega10_send_msg_to_smc,
601         .send_msg_to_smc_with_parameter = &vega10_send_msg_to_smc_with_parameter,
602         .download_pptable_settings = NULL,
603         .upload_pptable_settings = NULL,
604 };