xref: /linux/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega10_smumgr.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1e098bc96SEvan Quan /*
2e098bc96SEvan Quan  * Copyright 2016 Advanced Micro Devices, Inc.
3e098bc96SEvan Quan  *
4e098bc96SEvan Quan  * Permission is hereby granted, free of charge, to any person obtaining a
5e098bc96SEvan Quan  * copy of this software and associated documentation files (the "Software"),
6e098bc96SEvan Quan  * to deal in the Software without restriction, including without limitation
7e098bc96SEvan Quan  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8e098bc96SEvan Quan  * and/or sell copies of the Software, and to permit persons to whom the
9e098bc96SEvan Quan  * Software is furnished to do so, subject to the following conditions:
10e098bc96SEvan Quan  *
11e098bc96SEvan Quan  * The above copyright notice and this permission notice shall be included in
12e098bc96SEvan Quan  * all copies or substantial portions of the Software.
13e098bc96SEvan Quan  *
14e098bc96SEvan Quan  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15e098bc96SEvan Quan  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16e098bc96SEvan Quan  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17e098bc96SEvan Quan  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18e098bc96SEvan Quan  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19e098bc96SEvan Quan  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20e098bc96SEvan Quan  * OTHER DEALINGS IN THE SOFTWARE.
21e098bc96SEvan Quan  *
22e098bc96SEvan Quan  */
23e098bc96SEvan Quan 
24e098bc96SEvan Quan #include <linux/pci.h>
25e098bc96SEvan Quan 
26e098bc96SEvan Quan #include "smumgr.h"
27e098bc96SEvan Quan #include "vega10_inc.h"
28e098bc96SEvan Quan #include "soc15_common.h"
29e098bc96SEvan Quan #include "vega10_smumgr.h"
30e098bc96SEvan Quan #include "vega10_hwmgr.h"
31e098bc96SEvan Quan #include "vega10_ppsmc.h"
32e098bc96SEvan Quan #include "smu9_driver_if.h"
33e098bc96SEvan Quan #include "smu9_smumgr.h"
34e098bc96SEvan Quan #include "ppatomctrl.h"
35e098bc96SEvan Quan #include "pp_debug.h"
36e098bc96SEvan Quan 
37e098bc96SEvan Quan 
vega10_copy_table_from_smc(struct pp_hwmgr * hwmgr,uint8_t * table,int16_t table_id)38e098bc96SEvan Quan static int vega10_copy_table_from_smc(struct pp_hwmgr *hwmgr,
39e098bc96SEvan Quan 		uint8_t *table, int16_t table_id)
40e098bc96SEvan Quan {
41e098bc96SEvan Quan 	struct vega10_smumgr *priv = hwmgr->smu_backend;
42e098bc96SEvan Quan 	struct amdgpu_device *adev = hwmgr->adev;
43e098bc96SEvan Quan 
44e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
45e098bc96SEvan Quan 			"Invalid SMU Table ID!", return -EINVAL);
46e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
47e098bc96SEvan Quan 			"Invalid SMU Table version!", return -EINVAL);
48e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
49e098bc96SEvan Quan 			"Invalid SMU Table Length!", return -EINVAL);
50e098bc96SEvan Quan 	smum_send_msg_to_smc_with_parameter(hwmgr,
51e098bc96SEvan Quan 			PPSMC_MSG_SetDriverDramAddrHigh,
52e098bc96SEvan Quan 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
53e098bc96SEvan Quan 			NULL);
54e098bc96SEvan Quan 	smum_send_msg_to_smc_with_parameter(hwmgr,
55e098bc96SEvan Quan 			PPSMC_MSG_SetDriverDramAddrLow,
56e098bc96SEvan Quan 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
57e098bc96SEvan Quan 			NULL);
58e098bc96SEvan Quan 	smum_send_msg_to_smc_with_parameter(hwmgr,
59e098bc96SEvan Quan 			PPSMC_MSG_TransferTableSmu2Dram,
60e098bc96SEvan Quan 			priv->smu_tables.entry[table_id].table_id,
61e098bc96SEvan Quan 			NULL);
62e098bc96SEvan Quan 
630339258bSEvan Quan 	amdgpu_asic_invalidate_hdp(adev, NULL);
64e098bc96SEvan Quan 
65e098bc96SEvan Quan 	memcpy(table, priv->smu_tables.entry[table_id].table,
66e098bc96SEvan Quan 			priv->smu_tables.entry[table_id].size);
67e098bc96SEvan Quan 
68e098bc96SEvan Quan 	return 0;
69e098bc96SEvan Quan }
70e098bc96SEvan Quan 
vega10_copy_table_to_smc(struct pp_hwmgr * hwmgr,uint8_t * table,int16_t table_id)71e098bc96SEvan Quan static int vega10_copy_table_to_smc(struct pp_hwmgr *hwmgr,
72e098bc96SEvan Quan 		uint8_t *table, int16_t table_id)
73e098bc96SEvan Quan {
74e098bc96SEvan Quan 	struct vega10_smumgr *priv = hwmgr->smu_backend;
75e098bc96SEvan Quan 	struct amdgpu_device *adev = hwmgr->adev;
76e098bc96SEvan Quan 
77e098bc96SEvan Quan 	/* under sriov, vbios or hypervisor driver
78e098bc96SEvan Quan 	 * has already copy table to smc so here only skip it
79e098bc96SEvan Quan 	 */
80e098bc96SEvan Quan 	if (!hwmgr->not_vf)
81e098bc96SEvan Quan 		return 0;
82e098bc96SEvan Quan 
83e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(table_id < MAX_SMU_TABLE,
84e098bc96SEvan Quan 			"Invalid SMU Table ID!", return -EINVAL);
85e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].version != 0,
86e098bc96SEvan Quan 			"Invalid SMU Table version!", return -EINVAL);
87e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(priv->smu_tables.entry[table_id].size != 0,
88e098bc96SEvan Quan 			"Invalid SMU Table Length!", return -EINVAL);
89e098bc96SEvan Quan 
90e098bc96SEvan Quan 	memcpy(priv->smu_tables.entry[table_id].table, table,
91e098bc96SEvan Quan 			priv->smu_tables.entry[table_id].size);
92e098bc96SEvan Quan 
93e098bc96SEvan Quan 	amdgpu_asic_flush_hdp(adev, NULL);
94e098bc96SEvan Quan 
95e098bc96SEvan Quan 	smum_send_msg_to_smc_with_parameter(hwmgr,
96e098bc96SEvan Quan 			PPSMC_MSG_SetDriverDramAddrHigh,
97e098bc96SEvan Quan 			upper_32_bits(priv->smu_tables.entry[table_id].mc_addr),
98e098bc96SEvan Quan 			NULL);
99e098bc96SEvan Quan 	smum_send_msg_to_smc_with_parameter(hwmgr,
100e098bc96SEvan Quan 			PPSMC_MSG_SetDriverDramAddrLow,
101e098bc96SEvan Quan 			lower_32_bits(priv->smu_tables.entry[table_id].mc_addr),
102e098bc96SEvan Quan 			NULL);
103e098bc96SEvan Quan 	smum_send_msg_to_smc_with_parameter(hwmgr,
104e098bc96SEvan Quan 			PPSMC_MSG_TransferTableDram2Smu,
105e098bc96SEvan Quan 			priv->smu_tables.entry[table_id].table_id,
106e098bc96SEvan Quan 			NULL);
107e098bc96SEvan Quan 
108e098bc96SEvan Quan 	return 0;
109e098bc96SEvan Quan }
110e098bc96SEvan Quan 
vega10_enable_smc_features(struct pp_hwmgr * hwmgr,bool enable,uint32_t feature_mask)111e098bc96SEvan Quan int vega10_enable_smc_features(struct pp_hwmgr *hwmgr,
112e098bc96SEvan Quan 			       bool enable, uint32_t feature_mask)
113e098bc96SEvan Quan {
114e098bc96SEvan Quan 	int msg = enable ? PPSMC_MSG_EnableSmuFeatures :
115e098bc96SEvan Quan 			PPSMC_MSG_DisableSmuFeatures;
116e098bc96SEvan Quan 
117e098bc96SEvan Quan 	/* VF has no permission to change smu feature due
118e098bc96SEvan Quan 	 * to security concern even under pp one vf mode
119e098bc96SEvan Quan 	 * it still can't do it. For vega10, the smu in
120e098bc96SEvan Quan 	 * vbios will enable the appropriate features.
121e098bc96SEvan Quan 	 * */
122e098bc96SEvan Quan 	if (!hwmgr->not_vf)
123e098bc96SEvan Quan 		return 0;
124e098bc96SEvan Quan 
125e098bc96SEvan Quan 	return smum_send_msg_to_smc_with_parameter(hwmgr,
126e098bc96SEvan Quan 			msg, feature_mask, NULL);
127e098bc96SEvan Quan }
128e098bc96SEvan Quan 
vega10_get_enabled_smc_features(struct pp_hwmgr * hwmgr,uint64_t * features_enabled)129e098bc96SEvan Quan int vega10_get_enabled_smc_features(struct pp_hwmgr *hwmgr,
130e098bc96SEvan Quan 			    uint64_t *features_enabled)
131e098bc96SEvan Quan {
132e098bc96SEvan Quan 	uint32_t enabled_features;
133*5fa7d540STim Huang 	int ret;
134e098bc96SEvan Quan 
135e098bc96SEvan Quan 	if (features_enabled == NULL)
136e098bc96SEvan Quan 		return -EINVAL;
137e098bc96SEvan Quan 
138*5fa7d540STim Huang 	ret = smum_send_msg_to_smc(hwmgr,
139e098bc96SEvan Quan 			PPSMC_MSG_GetEnabledSmuFeatures,
140e098bc96SEvan Quan 			&enabled_features);
141*5fa7d540STim Huang 	if (ret)
142*5fa7d540STim Huang 		return ret;
143*5fa7d540STim Huang 
144e098bc96SEvan Quan 	*features_enabled = enabled_features;
145e098bc96SEvan Quan 
146e098bc96SEvan Quan 	return 0;
147e098bc96SEvan Quan }
148e098bc96SEvan Quan 
vega10_is_dpm_running(struct pp_hwmgr * hwmgr)149e098bc96SEvan Quan static bool vega10_is_dpm_running(struct pp_hwmgr *hwmgr)
150e098bc96SEvan Quan {
151e098bc96SEvan Quan 	uint64_t features_enabled = 0;
152e098bc96SEvan Quan 
153e098bc96SEvan Quan 	vega10_get_enabled_smc_features(hwmgr, &features_enabled);
154e098bc96SEvan Quan 
155e098bc96SEvan Quan 	if (features_enabled & SMC_DPM_FEATURES)
156e098bc96SEvan Quan 		return true;
157e098bc96SEvan Quan 	else
158e098bc96SEvan Quan 		return false;
159e098bc96SEvan Quan }
160e098bc96SEvan Quan 
vega10_set_tools_address(struct pp_hwmgr * hwmgr)161e098bc96SEvan Quan static int vega10_set_tools_address(struct pp_hwmgr *hwmgr)
162e098bc96SEvan Quan {
163e098bc96SEvan Quan 	struct vega10_smumgr *priv = hwmgr->smu_backend;
164e098bc96SEvan Quan 
165e098bc96SEvan Quan 	if (priv->smu_tables.entry[TOOLSTABLE].mc_addr) {
166e098bc96SEvan Quan 		smum_send_msg_to_smc_with_parameter(hwmgr,
167e098bc96SEvan Quan 				PPSMC_MSG_SetToolsDramAddrHigh,
168e098bc96SEvan Quan 				upper_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
169e098bc96SEvan Quan 				NULL);
170e098bc96SEvan Quan 		smum_send_msg_to_smc_with_parameter(hwmgr,
171e098bc96SEvan Quan 				PPSMC_MSG_SetToolsDramAddrLow,
172e098bc96SEvan Quan 				lower_32_bits(priv->smu_tables.entry[TOOLSTABLE].mc_addr),
173e098bc96SEvan Quan 				NULL);
174e098bc96SEvan Quan 	}
175e098bc96SEvan Quan 	return 0;
176e098bc96SEvan Quan }
177e098bc96SEvan Quan 
vega10_verify_smc_interface(struct pp_hwmgr * hwmgr)178e098bc96SEvan Quan static int vega10_verify_smc_interface(struct pp_hwmgr *hwmgr)
179e098bc96SEvan Quan {
180e098bc96SEvan Quan 	uint32_t smc_driver_if_version;
181e098bc96SEvan Quan 	struct amdgpu_device *adev = hwmgr->adev;
182e098bc96SEvan Quan 	uint32_t dev_id;
183e098bc96SEvan Quan 	uint32_t rev_id;
184e098bc96SEvan Quan 
185e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(!smum_send_msg_to_smc(hwmgr,
186e098bc96SEvan Quan 			PPSMC_MSG_GetDriverIfVersion,
187e098bc96SEvan Quan 			&smc_driver_if_version),
188e098bc96SEvan Quan 			"Attempt to get SMC IF Version Number Failed!",
189e098bc96SEvan Quan 			return -EINVAL);
190e098bc96SEvan Quan 
191e098bc96SEvan Quan 	dev_id = adev->pdev->device;
192e098bc96SEvan Quan 	rev_id = adev->pdev->revision;
193e098bc96SEvan Quan 
194e098bc96SEvan Quan 	if (!((dev_id == 0x687f) &&
195e098bc96SEvan Quan 		((rev_id == 0xc0) ||
196e098bc96SEvan Quan 		(rev_id == 0xc1) ||
197e098bc96SEvan Quan 		(rev_id == 0xc3)))) {
198e098bc96SEvan Quan 		if (smc_driver_if_version != SMU9_DRIVER_IF_VERSION) {
199e098bc96SEvan Quan 			pr_err("Your firmware(0x%x) doesn't match SMU9_DRIVER_IF_VERSION(0x%x). Please update your firmware!\n",
200e098bc96SEvan Quan 			       smc_driver_if_version, SMU9_DRIVER_IF_VERSION);
201e098bc96SEvan Quan 			return -EINVAL;
202e098bc96SEvan Quan 		}
203e098bc96SEvan Quan 	}
204e098bc96SEvan Quan 
205e098bc96SEvan Quan 	return 0;
206e098bc96SEvan Quan }
207e098bc96SEvan Quan 
vega10_smu_init(struct pp_hwmgr * hwmgr)208e098bc96SEvan Quan static int vega10_smu_init(struct pp_hwmgr *hwmgr)
209e098bc96SEvan Quan {
210e098bc96SEvan Quan 	struct vega10_smumgr *priv;
211e098bc96SEvan Quan 	unsigned long tools_size;
212e098bc96SEvan Quan 	int ret;
213e098bc96SEvan Quan 	struct cgs_firmware_info info = {0};
214e098bc96SEvan Quan 
215e098bc96SEvan Quan 	ret = cgs_get_firmware_info(hwmgr->device,
216e098bc96SEvan Quan 					CGS_UCODE_ID_SMU,
217e098bc96SEvan Quan 					&info);
218e098bc96SEvan Quan 	if (ret || !info.kptr)
219e098bc96SEvan Quan 		return -EINVAL;
220e098bc96SEvan Quan 
221e098bc96SEvan Quan 	priv = kzalloc(sizeof(struct vega10_smumgr), GFP_KERNEL);
222e098bc96SEvan Quan 
223e098bc96SEvan Quan 	if (!priv)
224e098bc96SEvan Quan 		return -ENOMEM;
225e098bc96SEvan Quan 
226e098bc96SEvan Quan 	hwmgr->smu_backend = priv;
227e098bc96SEvan Quan 
228e098bc96SEvan Quan 	/* allocate space for pptable */
229e098bc96SEvan Quan 	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
230e098bc96SEvan Quan 			sizeof(PPTable_t),
231e098bc96SEvan Quan 			PAGE_SIZE,
232e098bc96SEvan Quan 			AMDGPU_GEM_DOMAIN_VRAM,
233e098bc96SEvan Quan 			&priv->smu_tables.entry[PPTABLE].handle,
234e098bc96SEvan Quan 			&priv->smu_tables.entry[PPTABLE].mc_addr,
235e098bc96SEvan Quan 			&priv->smu_tables.entry[PPTABLE].table);
236e098bc96SEvan Quan 	if (ret)
237e098bc96SEvan Quan 		goto free_backend;
238e098bc96SEvan Quan 
239e098bc96SEvan Quan 	priv->smu_tables.entry[PPTABLE].version = 0x01;
240e098bc96SEvan Quan 	priv->smu_tables.entry[PPTABLE].size = sizeof(PPTable_t);
241e098bc96SEvan Quan 	priv->smu_tables.entry[PPTABLE].table_id = TABLE_PPTABLE;
242e098bc96SEvan Quan 
243e098bc96SEvan Quan 	/* allocate space for watermarks table */
244e098bc96SEvan Quan 	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
245e098bc96SEvan Quan 			sizeof(Watermarks_t),
246e098bc96SEvan Quan 			PAGE_SIZE,
247e098bc96SEvan Quan 			AMDGPU_GEM_DOMAIN_VRAM,
248e098bc96SEvan Quan 			&priv->smu_tables.entry[WMTABLE].handle,
249e098bc96SEvan Quan 			&priv->smu_tables.entry[WMTABLE].mc_addr,
250e098bc96SEvan Quan 			&priv->smu_tables.entry[WMTABLE].table);
251e098bc96SEvan Quan 
252e098bc96SEvan Quan 	if (ret)
253e098bc96SEvan Quan 		goto err0;
254e098bc96SEvan Quan 
255e098bc96SEvan Quan 	priv->smu_tables.entry[WMTABLE].version = 0x01;
256e098bc96SEvan Quan 	priv->smu_tables.entry[WMTABLE].size = sizeof(Watermarks_t);
257e098bc96SEvan Quan 	priv->smu_tables.entry[WMTABLE].table_id = TABLE_WATERMARKS;
258e098bc96SEvan Quan 
259e098bc96SEvan Quan 	/* allocate space for AVFS table */
260e098bc96SEvan Quan 	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
261e098bc96SEvan Quan 			sizeof(AvfsTable_t),
262e098bc96SEvan Quan 			PAGE_SIZE,
263e098bc96SEvan Quan 			AMDGPU_GEM_DOMAIN_VRAM,
264e098bc96SEvan Quan 			&priv->smu_tables.entry[AVFSTABLE].handle,
265e098bc96SEvan Quan 			&priv->smu_tables.entry[AVFSTABLE].mc_addr,
266e098bc96SEvan Quan 			&priv->smu_tables.entry[AVFSTABLE].table);
267e098bc96SEvan Quan 
268e098bc96SEvan Quan 	if (ret)
269e098bc96SEvan Quan 		goto err1;
270e098bc96SEvan Quan 
271e098bc96SEvan Quan 	priv->smu_tables.entry[AVFSTABLE].version = 0x01;
272e098bc96SEvan Quan 	priv->smu_tables.entry[AVFSTABLE].size = sizeof(AvfsTable_t);
273e098bc96SEvan Quan 	priv->smu_tables.entry[AVFSTABLE].table_id = TABLE_AVFS;
274e098bc96SEvan Quan 
275e098bc96SEvan Quan 	tools_size = 0x19000;
276e098bc96SEvan Quan 	if (tools_size) {
277e098bc96SEvan Quan 		ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
278e098bc96SEvan Quan 				tools_size,
279e098bc96SEvan Quan 				PAGE_SIZE,
280e098bc96SEvan Quan 				AMDGPU_GEM_DOMAIN_VRAM,
281e098bc96SEvan Quan 				&priv->smu_tables.entry[TOOLSTABLE].handle,
282e098bc96SEvan Quan 				&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
283e098bc96SEvan Quan 				&priv->smu_tables.entry[TOOLSTABLE].table);
284e098bc96SEvan Quan 		if (ret)
285e098bc96SEvan Quan 			goto err2;
286e098bc96SEvan Quan 		priv->smu_tables.entry[TOOLSTABLE].version = 0x01;
287e098bc96SEvan Quan 		priv->smu_tables.entry[TOOLSTABLE].size = tools_size;
288e098bc96SEvan Quan 		priv->smu_tables.entry[TOOLSTABLE].table_id = TABLE_PMSTATUSLOG;
289e098bc96SEvan Quan 	}
290e098bc96SEvan Quan 
291e098bc96SEvan Quan 	/* allocate space for AVFS Fuse table */
292e098bc96SEvan Quan 	ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
293e098bc96SEvan Quan 			sizeof(AvfsFuseOverride_t),
294e098bc96SEvan Quan 			PAGE_SIZE,
295e098bc96SEvan Quan 			AMDGPU_GEM_DOMAIN_VRAM,
296e098bc96SEvan Quan 			&priv->smu_tables.entry[AVFSFUSETABLE].handle,
297e098bc96SEvan Quan 			&priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
298e098bc96SEvan Quan 			&priv->smu_tables.entry[AVFSFUSETABLE].table);
299e098bc96SEvan Quan 	if (ret)
300e098bc96SEvan Quan 		goto err3;
301e098bc96SEvan Quan 
302e098bc96SEvan Quan 	priv->smu_tables.entry[AVFSFUSETABLE].version = 0x01;
303e098bc96SEvan Quan 	priv->smu_tables.entry[AVFSFUSETABLE].size = sizeof(AvfsFuseOverride_t);
304e098bc96SEvan Quan 	priv->smu_tables.entry[AVFSFUSETABLE].table_id = TABLE_AVFS_FUSE_OVERRIDE;
305e098bc96SEvan Quan 
306e098bc96SEvan Quan 
307e098bc96SEvan Quan 	return 0;
308e098bc96SEvan Quan 
309e098bc96SEvan Quan err3:
310e098bc96SEvan Quan 	if (priv->smu_tables.entry[TOOLSTABLE].table)
311e098bc96SEvan Quan 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
312e098bc96SEvan Quan 				&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
313e098bc96SEvan Quan 				&priv->smu_tables.entry[TOOLSTABLE].table);
314e098bc96SEvan Quan err2:
315e098bc96SEvan Quan 	amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
316e098bc96SEvan Quan 				&priv->smu_tables.entry[AVFSTABLE].mc_addr,
317e098bc96SEvan Quan 				&priv->smu_tables.entry[AVFSTABLE].table);
318e098bc96SEvan Quan err1:
319e098bc96SEvan Quan 	amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
320e098bc96SEvan Quan 				&priv->smu_tables.entry[WMTABLE].mc_addr,
321e098bc96SEvan Quan 				&priv->smu_tables.entry[WMTABLE].table);
322e098bc96SEvan Quan err0:
323e098bc96SEvan Quan 	amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
324e098bc96SEvan Quan 			&priv->smu_tables.entry[PPTABLE].mc_addr,
325e098bc96SEvan Quan 			&priv->smu_tables.entry[PPTABLE].table);
326e098bc96SEvan Quan free_backend:
327e098bc96SEvan Quan 	kfree(hwmgr->smu_backend);
328e098bc96SEvan Quan 
329e098bc96SEvan Quan 	return -EINVAL;
330e098bc96SEvan Quan }
331e098bc96SEvan Quan 
vega10_smu_fini(struct pp_hwmgr * hwmgr)332e098bc96SEvan Quan static int vega10_smu_fini(struct pp_hwmgr *hwmgr)
333e098bc96SEvan Quan {
334e098bc96SEvan Quan 	struct vega10_smumgr *priv = hwmgr->smu_backend;
335e098bc96SEvan Quan 
336e098bc96SEvan Quan 	if (priv) {
337e098bc96SEvan Quan 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[PPTABLE].handle,
338e098bc96SEvan Quan 				&priv->smu_tables.entry[PPTABLE].mc_addr,
339e098bc96SEvan Quan 				&priv->smu_tables.entry[PPTABLE].table);
340e098bc96SEvan Quan 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[WMTABLE].handle,
341e098bc96SEvan Quan 					&priv->smu_tables.entry[WMTABLE].mc_addr,
342e098bc96SEvan Quan 					&priv->smu_tables.entry[WMTABLE].table);
343e098bc96SEvan Quan 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSTABLE].handle,
344e098bc96SEvan Quan 					&priv->smu_tables.entry[AVFSTABLE].mc_addr,
345e098bc96SEvan Quan 					&priv->smu_tables.entry[AVFSTABLE].table);
346e098bc96SEvan Quan 		if (priv->smu_tables.entry[TOOLSTABLE].table)
347e098bc96SEvan Quan 			amdgpu_bo_free_kernel(&priv->smu_tables.entry[TOOLSTABLE].handle,
348e098bc96SEvan Quan 					&priv->smu_tables.entry[TOOLSTABLE].mc_addr,
349e098bc96SEvan Quan 					&priv->smu_tables.entry[TOOLSTABLE].table);
350e098bc96SEvan Quan 		amdgpu_bo_free_kernel(&priv->smu_tables.entry[AVFSFUSETABLE].handle,
351e098bc96SEvan Quan 					&priv->smu_tables.entry[AVFSFUSETABLE].mc_addr,
352e098bc96SEvan Quan 					&priv->smu_tables.entry[AVFSFUSETABLE].table);
353e098bc96SEvan Quan 		kfree(hwmgr->smu_backend);
354e098bc96SEvan Quan 		hwmgr->smu_backend = NULL;
355e098bc96SEvan Quan 	}
356e098bc96SEvan Quan 	return 0;
357e098bc96SEvan Quan }
358e098bc96SEvan Quan 
vega10_start_smu(struct pp_hwmgr * hwmgr)359e098bc96SEvan Quan static int vega10_start_smu(struct pp_hwmgr *hwmgr)
360e098bc96SEvan Quan {
361e098bc96SEvan Quan 	if (!smu9_is_smc_ram_running(hwmgr))
362e098bc96SEvan Quan 		return -EINVAL;
363e098bc96SEvan Quan 
364e098bc96SEvan Quan 	PP_ASSERT_WITH_CODE(!vega10_verify_smc_interface(hwmgr),
365e098bc96SEvan Quan 			"Failed to verify SMC interface!",
366e098bc96SEvan Quan 			return -EINVAL);
367e098bc96SEvan Quan 
368e098bc96SEvan Quan 	vega10_set_tools_address(hwmgr);
369e098bc96SEvan Quan 
370e098bc96SEvan Quan 	return 0;
371e098bc96SEvan Quan }
372e098bc96SEvan Quan 
vega10_smc_table_manager(struct pp_hwmgr * hwmgr,uint8_t * table,uint16_t table_id,bool rw)373e098bc96SEvan Quan static int vega10_smc_table_manager(struct pp_hwmgr *hwmgr, uint8_t *table,
374e098bc96SEvan Quan 				    uint16_t table_id, bool rw)
375e098bc96SEvan Quan {
376e098bc96SEvan Quan 	int ret;
377e098bc96SEvan Quan 
378e098bc96SEvan Quan 	if (rw)
379e098bc96SEvan Quan 		ret = vega10_copy_table_from_smc(hwmgr, table, table_id);
380e098bc96SEvan Quan 	else
381e098bc96SEvan Quan 		ret = vega10_copy_table_to_smc(hwmgr, table, table_id);
382e098bc96SEvan Quan 
383e098bc96SEvan Quan 	return ret;
384e098bc96SEvan Quan }
385e098bc96SEvan Quan 
386e098bc96SEvan Quan const struct pp_smumgr_func vega10_smu_funcs = {
387e098bc96SEvan Quan 	.name = "vega10_smu",
388e098bc96SEvan Quan 	.smu_init = &vega10_smu_init,
389e098bc96SEvan Quan 	.smu_fini = &vega10_smu_fini,
390e098bc96SEvan Quan 	.start_smu = &vega10_start_smu,
391e098bc96SEvan Quan 	.request_smu_load_specific_fw = NULL,
392e098bc96SEvan Quan 	.send_msg_to_smc = &smu9_send_msg_to_smc,
393e098bc96SEvan Quan 	.send_msg_to_smc_with_parameter = &smu9_send_msg_to_smc_with_parameter,
394e098bc96SEvan Quan 	.download_pptable_settings = NULL,
395e098bc96SEvan Quan 	.upload_pptable_settings = NULL,
396e098bc96SEvan Quan 	.is_dpm_running = vega10_is_dpm_running,
397e098bc96SEvan Quan 	.get_argument = smu9_get_argument,
398e098bc96SEvan Quan 	.smc_table_manager = vega10_smc_table_manager,
399e098bc96SEvan Quan };
400