xref: /openbsd-src/sys/dev/pci/drm/amd/amdgpu/amdgpu_psp.c (revision 99dcd02b784a6b5cceb6c35fcfc710db14459446)
1fb4d8502Sjsg /*
2fb4d8502Sjsg  * Copyright 2016 Advanced Micro Devices, Inc.
3fb4d8502Sjsg  *
4fb4d8502Sjsg  * Permission is hereby granted, free of charge, to any person obtaining a
5fb4d8502Sjsg  * copy of this software and associated documentation files (the "Software"),
6fb4d8502Sjsg  * to deal in the Software without restriction, including without limitation
7fb4d8502Sjsg  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fb4d8502Sjsg  * and/or sell copies of the Software, and to permit persons to whom the
9fb4d8502Sjsg  * Software is furnished to do so, subject to the following conditions:
10fb4d8502Sjsg  *
11fb4d8502Sjsg  * The above copyright notice and this permission notice shall be included in
12fb4d8502Sjsg  * all copies or substantial portions of the Software.
13fb4d8502Sjsg  *
14fb4d8502Sjsg  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17fb4d8502Sjsg  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18fb4d8502Sjsg  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19fb4d8502Sjsg  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20fb4d8502Sjsg  * OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg  *
22fb4d8502Sjsg  * Author: Huang Rui
23fb4d8502Sjsg  *
24fb4d8502Sjsg  */
25fb4d8502Sjsg 
26fb4d8502Sjsg #include <linux/firmware.h>
275ca02815Sjsg #include <drm/drm_drv.h>
28c349dbc7Sjsg 
29fb4d8502Sjsg #include "amdgpu.h"
30fb4d8502Sjsg #include "amdgpu_psp.h"
31fb4d8502Sjsg #include "amdgpu_ucode.h"
325ca02815Sjsg #include "amdgpu_xgmi.h"
33fb4d8502Sjsg #include "soc15_common.h"
34fb4d8502Sjsg #include "psp_v3_1.h"
35fb4d8502Sjsg #include "psp_v10_0.h"
36c349dbc7Sjsg #include "psp_v11_0.h"
375ca02815Sjsg #include "psp_v11_0_8.h"
38c349dbc7Sjsg #include "psp_v12_0.h"
395ca02815Sjsg #include "psp_v13_0.h"
401bb76ff1Sjsg #include "psp_v13_0_4.h"
41c349dbc7Sjsg 
42c349dbc7Sjsg #include "amdgpu_ras.h"
435ca02815Sjsg #include "amdgpu_securedisplay.h"
445ca02815Sjsg #include "amdgpu_atomfirmware.h"
45fb4d8502Sjsg 
461bb76ff1Sjsg #define AMD_VBIOS_FILE_MAX_SIZE_B      (1024*1024*3)
471bb76ff1Sjsg 
48ad8b1aafSjsg static int psp_load_smu_fw(struct psp_context *psp);
491bb76ff1Sjsg static int psp_rap_terminate(struct psp_context *psp);
501bb76ff1Sjsg static int psp_securedisplay_terminate(struct psp_context *psp);
51ad8b1aafSjsg 
52f005ef32Sjsg static int psp_ring_init(struct psp_context *psp,
53f005ef32Sjsg 			 enum psp_ring_type ring_type)
54f005ef32Sjsg {
55f005ef32Sjsg 	int ret = 0;
56f005ef32Sjsg 	struct psp_ring *ring;
57f005ef32Sjsg 	struct amdgpu_device *adev = psp->adev;
58f005ef32Sjsg 
59f005ef32Sjsg 	ring = &psp->km_ring;
60f005ef32Sjsg 
61f005ef32Sjsg 	ring->ring_type = ring_type;
62f005ef32Sjsg 
63f005ef32Sjsg 	/* allocate 4k Page of Local Frame Buffer memory for ring */
64f005ef32Sjsg 	ring->ring_size = 0x1000;
65f005ef32Sjsg 	ret = amdgpu_bo_create_kernel(adev, ring->ring_size, PAGE_SIZE,
66f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_VRAM |
67f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_GTT,
68f005ef32Sjsg 				      &adev->firmware.rbuf,
69f005ef32Sjsg 				      &ring->ring_mem_mc_addr,
70f005ef32Sjsg 				      (void **)&ring->ring_mem);
71f005ef32Sjsg 	if (ret) {
72f005ef32Sjsg 		ring->ring_size = 0;
73f005ef32Sjsg 		return ret;
74f005ef32Sjsg 	}
75f005ef32Sjsg 
76f005ef32Sjsg 	return 0;
77f005ef32Sjsg }
78f005ef32Sjsg 
79c349dbc7Sjsg /*
80c349dbc7Sjsg  * Due to DF Cstate management centralized to PMFW, the firmware
81c349dbc7Sjsg  * loading sequence will be updated as below:
82c349dbc7Sjsg  *   - Load KDB
83c349dbc7Sjsg  *   - Load SYS_DRV
84c349dbc7Sjsg  *   - Load tOS
85c349dbc7Sjsg  *   - Load PMFW
86c349dbc7Sjsg  *   - Setup TMR
87c349dbc7Sjsg  *   - Load other non-psp fw
88c349dbc7Sjsg  *   - Load ASD
89c349dbc7Sjsg  *   - Load XGMI/RAS/HDCP/DTM TA if any
90c349dbc7Sjsg  *
91c349dbc7Sjsg  * This new sequence is required for
925ca02815Sjsg  *   - Arcturus and onwards
93c349dbc7Sjsg  */
94c349dbc7Sjsg static void psp_check_pmfw_centralized_cstate_management(struct psp_context *psp)
95c349dbc7Sjsg {
96c349dbc7Sjsg 	struct amdgpu_device *adev = psp->adev;
97c349dbc7Sjsg 
981bb76ff1Sjsg 	if (amdgpu_sriov_vf(adev)) {
99c349dbc7Sjsg 		psp->pmfw_centralized_cstate_management = false;
100c349dbc7Sjsg 		return;
1011bb76ff1Sjsg 	}
102c349dbc7Sjsg 
1031bb76ff1Sjsg 	switch (adev->ip_versions[MP0_HWIP][0]) {
1041bb76ff1Sjsg 	case IP_VERSION(11, 0, 0):
1051bb76ff1Sjsg 	case IP_VERSION(11, 0, 4):
1061bb76ff1Sjsg 	case IP_VERSION(11, 0, 5):
1071bb76ff1Sjsg 	case IP_VERSION(11, 0, 7):
1081bb76ff1Sjsg 	case IP_VERSION(11, 0, 9):
1091bb76ff1Sjsg 	case IP_VERSION(11, 0, 11):
1101bb76ff1Sjsg 	case IP_VERSION(11, 0, 12):
1111bb76ff1Sjsg 	case IP_VERSION(11, 0, 13):
1121bb76ff1Sjsg 	case IP_VERSION(13, 0, 0):
1131bb76ff1Sjsg 	case IP_VERSION(13, 0, 2):
1141bb76ff1Sjsg 	case IP_VERSION(13, 0, 7):
115c349dbc7Sjsg 		psp->pmfw_centralized_cstate_management = true;
1161bb76ff1Sjsg 		break;
1171bb76ff1Sjsg 	default:
1181bb76ff1Sjsg 		psp->pmfw_centralized_cstate_management = false;
1191bb76ff1Sjsg 		break;
1201bb76ff1Sjsg 	}
121c349dbc7Sjsg }
122c349dbc7Sjsg 
123f005ef32Sjsg static int psp_init_sriov_microcode(struct psp_context *psp)
124f005ef32Sjsg {
125f005ef32Sjsg 	struct amdgpu_device *adev = psp->adev;
126f005ef32Sjsg 	char ucode_prefix[30];
127f005ef32Sjsg 	int ret = 0;
128f005ef32Sjsg 
129f005ef32Sjsg 	amdgpu_ucode_ip_version_decode(adev, MP0_HWIP, ucode_prefix, sizeof(ucode_prefix));
130f005ef32Sjsg 
131f005ef32Sjsg 	switch (adev->ip_versions[MP0_HWIP][0]) {
132f005ef32Sjsg 	case IP_VERSION(9, 0, 0):
133f005ef32Sjsg 	case IP_VERSION(11, 0, 7):
134f005ef32Sjsg 	case IP_VERSION(11, 0, 9):
135f005ef32Sjsg 		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
136f005ef32Sjsg 		ret = psp_init_cap_microcode(psp, ucode_prefix);
137f005ef32Sjsg 		break;
138f005ef32Sjsg 	case IP_VERSION(13, 0, 2):
139f005ef32Sjsg 		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MEC2;
140f005ef32Sjsg 		ret = psp_init_cap_microcode(psp, ucode_prefix);
141f005ef32Sjsg 		ret &= psp_init_ta_microcode(psp, ucode_prefix);
142f005ef32Sjsg 		break;
143f005ef32Sjsg 	case IP_VERSION(13, 0, 0):
144f005ef32Sjsg 		adev->virt.autoload_ucode_id = 0;
145f005ef32Sjsg 		break;
146f005ef32Sjsg 	case IP_VERSION(13, 0, 6):
147f005ef32Sjsg 		ret = psp_init_cap_microcode(psp, ucode_prefix);
148f005ef32Sjsg 		ret &= psp_init_ta_microcode(psp, ucode_prefix);
149f005ef32Sjsg 		break;
150f005ef32Sjsg 	case IP_VERSION(13, 0, 10):
151f005ef32Sjsg 		adev->virt.autoload_ucode_id = AMDGPU_UCODE_ID_CP_MES1_DATA;
152f005ef32Sjsg 		ret = psp_init_cap_microcode(psp, ucode_prefix);
153f005ef32Sjsg 		break;
154f005ef32Sjsg 	default:
155f005ef32Sjsg 		return -EINVAL;
156f005ef32Sjsg 	}
157f005ef32Sjsg 	return ret;
158f005ef32Sjsg }
159f005ef32Sjsg 
160fb4d8502Sjsg static int psp_early_init(void *handle)
161fb4d8502Sjsg {
162fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
163c8a1e887Sjsg 	struct psp_context *psp = &adev->psp;
164fb4d8502Sjsg 
1651bb76ff1Sjsg 	switch (adev->ip_versions[MP0_HWIP][0]) {
1661bb76ff1Sjsg 	case IP_VERSION(9, 0, 0):
167fb4d8502Sjsg 		psp_v3_1_set_psp_funcs(psp);
168c349dbc7Sjsg 		psp->autoload_supported = false;
169fb4d8502Sjsg 		break;
1701bb76ff1Sjsg 	case IP_VERSION(10, 0, 0):
1711bb76ff1Sjsg 	case IP_VERSION(10, 0, 1):
172fb4d8502Sjsg 		psp_v10_0_set_psp_funcs(psp);
173c349dbc7Sjsg 		psp->autoload_supported = false;
174c349dbc7Sjsg 		break;
1751bb76ff1Sjsg 	case IP_VERSION(11, 0, 2):
1761bb76ff1Sjsg 	case IP_VERSION(11, 0, 4):
177c349dbc7Sjsg 		psp_v11_0_set_psp_funcs(psp);
178c349dbc7Sjsg 		psp->autoload_supported = false;
179c349dbc7Sjsg 		break;
1801bb76ff1Sjsg 	case IP_VERSION(11, 0, 0):
181f005ef32Sjsg 	case IP_VERSION(11, 0, 7):
182f005ef32Sjsg 		adev->psp.sup_pd_fw_up = !amdgpu_sriov_vf(adev);
183f005ef32Sjsg 		fallthrough;
1841bb76ff1Sjsg 	case IP_VERSION(11, 0, 5):
1851bb76ff1Sjsg 	case IP_VERSION(11, 0, 9):
1861bb76ff1Sjsg 	case IP_VERSION(11, 0, 11):
1871bb76ff1Sjsg 	case IP_VERSION(11, 5, 0):
1881bb76ff1Sjsg 	case IP_VERSION(11, 0, 12):
1891bb76ff1Sjsg 	case IP_VERSION(11, 0, 13):
190c349dbc7Sjsg 		psp_v11_0_set_psp_funcs(psp);
191c349dbc7Sjsg 		psp->autoload_supported = true;
192c349dbc7Sjsg 		break;
1931bb76ff1Sjsg 	case IP_VERSION(11, 0, 3):
1941bb76ff1Sjsg 	case IP_VERSION(12, 0, 1):
195c349dbc7Sjsg 		psp_v12_0_set_psp_funcs(psp);
196fb4d8502Sjsg 		break;
1971bb76ff1Sjsg 	case IP_VERSION(13, 0, 2):
198f005ef32Sjsg 	case IP_VERSION(13, 0, 6):
1995ca02815Sjsg 		psp_v13_0_set_psp_funcs(psp);
2005ca02815Sjsg 		break;
2011bb76ff1Sjsg 	case IP_VERSION(13, 0, 1):
2021bb76ff1Sjsg 	case IP_VERSION(13, 0, 3):
2031bb76ff1Sjsg 	case IP_VERSION(13, 0, 5):
2041bb76ff1Sjsg 	case IP_VERSION(13, 0, 8):
205d424a9b5Sjsg 	case IP_VERSION(13, 0, 11):
206f005ef32Sjsg 	case IP_VERSION(14, 0, 0):
2075ca02815Sjsg 		psp_v13_0_set_psp_funcs(psp);
2085ca02815Sjsg 		psp->autoload_supported = true;
2095ca02815Sjsg 		break;
2101bb76ff1Sjsg 	case IP_VERSION(11, 0, 8):
2115ca02815Sjsg 		if (adev->apu_flags & AMD_APU_IS_CYAN_SKILLFISH2) {
2125ca02815Sjsg 			psp_v11_0_8_set_psp_funcs(psp);
2135ca02815Sjsg 			psp->autoload_supported = false;
2145ca02815Sjsg 		}
2155ca02815Sjsg 		break;
2161bb76ff1Sjsg 	case IP_VERSION(13, 0, 0):
2171bb76ff1Sjsg 	case IP_VERSION(13, 0, 7):
218f005ef32Sjsg 	case IP_VERSION(13, 0, 10):
2191bb76ff1Sjsg 		psp_v13_0_set_psp_funcs(psp);
2201bb76ff1Sjsg 		psp->autoload_supported = true;
221f005ef32Sjsg 		adev->psp.sup_ifwi_up = !amdgpu_sriov_vf(adev);
2221bb76ff1Sjsg 		break;
2231bb76ff1Sjsg 	case IP_VERSION(13, 0, 4):
2241bb76ff1Sjsg 		psp_v13_0_4_set_psp_funcs(psp);
2251bb76ff1Sjsg 		psp->autoload_supported = true;
2261bb76ff1Sjsg 		break;
227fb4d8502Sjsg 	default:
228fb4d8502Sjsg 		return -EINVAL;
229fb4d8502Sjsg 	}
230fb4d8502Sjsg 
231fb4d8502Sjsg 	psp->adev = adev;
232fb4d8502Sjsg 
233c349dbc7Sjsg 	psp_check_pmfw_centralized_cstate_management(psp);
234fb4d8502Sjsg 
235f005ef32Sjsg 	if (amdgpu_sriov_vf(adev))
236f005ef32Sjsg 		return psp_init_sriov_microcode(psp);
237f005ef32Sjsg 	else
238f005ef32Sjsg 		return psp_init_microcode(psp);
239c8a1e887Sjsg }
240c8a1e887Sjsg 
2411bb76ff1Sjsg void psp_ta_free_shared_buf(struct ta_mem_context *mem_ctx)
2421bb76ff1Sjsg {
2431bb76ff1Sjsg 	amdgpu_bo_free_kernel(&mem_ctx->shared_bo, &mem_ctx->shared_mc_addr,
2441bb76ff1Sjsg 			      &mem_ctx->shared_buf);
2451bb76ff1Sjsg 	mem_ctx->shared_bo = NULL;
2461bb76ff1Sjsg }
2471bb76ff1Sjsg 
2481bb76ff1Sjsg static void psp_free_shared_bufs(struct psp_context *psp)
2491bb76ff1Sjsg {
2501bb76ff1Sjsg 	void *tmr_buf;
2511bb76ff1Sjsg 	void **pptr;
2521bb76ff1Sjsg 
2531bb76ff1Sjsg 	/* free TMR memory buffer */
2541bb76ff1Sjsg 	pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
2551bb76ff1Sjsg 	amdgpu_bo_free_kernel(&psp->tmr_bo, &psp->tmr_mc_addr, pptr);
2561bb76ff1Sjsg 	psp->tmr_bo = NULL;
2571bb76ff1Sjsg 
2581bb76ff1Sjsg 	/* free xgmi shared memory */
2591bb76ff1Sjsg 	psp_ta_free_shared_buf(&psp->xgmi_context.context.mem_context);
2601bb76ff1Sjsg 
2611bb76ff1Sjsg 	/* free ras shared memory */
2621bb76ff1Sjsg 	psp_ta_free_shared_buf(&psp->ras_context.context.mem_context);
2631bb76ff1Sjsg 
2641bb76ff1Sjsg 	/* free hdcp shared memory */
2651bb76ff1Sjsg 	psp_ta_free_shared_buf(&psp->hdcp_context.context.mem_context);
2661bb76ff1Sjsg 
2671bb76ff1Sjsg 	/* free dtm shared memory */
2681bb76ff1Sjsg 	psp_ta_free_shared_buf(&psp->dtm_context.context.mem_context);
2691bb76ff1Sjsg 
2701bb76ff1Sjsg 	/* free rap shared memory */
2711bb76ff1Sjsg 	psp_ta_free_shared_buf(&psp->rap_context.context.mem_context);
2721bb76ff1Sjsg 
2731bb76ff1Sjsg 	/* free securedisplay shared memory */
2741bb76ff1Sjsg 	psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context);
2751bb76ff1Sjsg 
2761bb76ff1Sjsg 
2771bb76ff1Sjsg }
2781bb76ff1Sjsg 
279ad8b1aafSjsg static void psp_memory_training_fini(struct psp_context *psp)
280ad8b1aafSjsg {
281ad8b1aafSjsg 	struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
282ad8b1aafSjsg 
283ad8b1aafSjsg 	ctx->init = PSP_MEM_TRAIN_NOT_SUPPORT;
284ad8b1aafSjsg 	kfree(ctx->sys_cache);
285ad8b1aafSjsg 	ctx->sys_cache = NULL;
286ad8b1aafSjsg }
287ad8b1aafSjsg 
288ad8b1aafSjsg static int psp_memory_training_init(struct psp_context *psp)
289ad8b1aafSjsg {
290ad8b1aafSjsg 	int ret;
291ad8b1aafSjsg 	struct psp_memory_training_context *ctx = &psp->mem_train_ctx;
292ad8b1aafSjsg 
293ad8b1aafSjsg 	if (ctx->init != PSP_MEM_TRAIN_RESERVE_SUCCESS) {
294ad8b1aafSjsg 		DRM_DEBUG("memory training is not supported!\n");
295ad8b1aafSjsg 		return 0;
296ad8b1aafSjsg 	}
297ad8b1aafSjsg 
298ad8b1aafSjsg 	ctx->sys_cache = kzalloc(ctx->train_data_size, GFP_KERNEL);
299ad8b1aafSjsg 	if (ctx->sys_cache == NULL) {
300ad8b1aafSjsg 		DRM_ERROR("alloc mem_train_ctx.sys_cache failed!\n");
301ad8b1aafSjsg 		ret = -ENOMEM;
302ad8b1aafSjsg 		goto Err_out;
303ad8b1aafSjsg 	}
304ad8b1aafSjsg 
305ad8b1aafSjsg 	DRM_DEBUG("train_data_size:%llx,p2c_train_data_offset:%llx,c2p_train_data_offset:%llx.\n",
306ad8b1aafSjsg 		  ctx->train_data_size,
307ad8b1aafSjsg 		  ctx->p2c_train_data_offset,
308ad8b1aafSjsg 		  ctx->c2p_train_data_offset);
309ad8b1aafSjsg 	ctx->init = PSP_MEM_TRAIN_INIT_SUCCESS;
310ad8b1aafSjsg 	return 0;
311ad8b1aafSjsg 
312ad8b1aafSjsg Err_out:
313ad8b1aafSjsg 	psp_memory_training_fini(psp);
314ad8b1aafSjsg 	return ret;
315ad8b1aafSjsg }
316ad8b1aafSjsg 
3175ca02815Sjsg /*
3185ca02815Sjsg  * Helper funciton to query psp runtime database entry
3195ca02815Sjsg  *
3205ca02815Sjsg  * @adev: amdgpu_device pointer
3215ca02815Sjsg  * @entry_type: the type of psp runtime database entry
3225ca02815Sjsg  * @db_entry: runtime database entry pointer
3235ca02815Sjsg  *
3245ca02815Sjsg  * Return false if runtime database doesn't exit or entry is invalid
3255ca02815Sjsg  * or true if the specific database entry is found, and copy to @db_entry
3265ca02815Sjsg  */
3275ca02815Sjsg static bool psp_get_runtime_db_entry(struct amdgpu_device *adev,
3285ca02815Sjsg 				     enum psp_runtime_entry_type entry_type,
3295ca02815Sjsg 				     void *db_entry)
3305ca02815Sjsg {
3315ca02815Sjsg 	uint64_t db_header_pos, db_dir_pos;
3325ca02815Sjsg 	struct psp_runtime_data_header db_header = {0};
3335ca02815Sjsg 	struct psp_runtime_data_directory db_dir = {0};
3345ca02815Sjsg 	bool ret = false;
3355ca02815Sjsg 	int i;
3365ca02815Sjsg 
337f005ef32Sjsg 	if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6))
338f005ef32Sjsg 		return false;
339f005ef32Sjsg 
3405ca02815Sjsg 	db_header_pos = adev->gmc.mc_vram_size - PSP_RUNTIME_DB_OFFSET;
3415ca02815Sjsg 	db_dir_pos = db_header_pos + sizeof(struct psp_runtime_data_header);
3425ca02815Sjsg 
3435ca02815Sjsg 	/* read runtime db header from vram */
3445ca02815Sjsg 	amdgpu_device_vram_access(adev, db_header_pos, (uint32_t *)&db_header,
3455ca02815Sjsg 			sizeof(struct psp_runtime_data_header), false);
3465ca02815Sjsg 
3475ca02815Sjsg 	if (db_header.cookie != PSP_RUNTIME_DB_COOKIE_ID) {
3485ca02815Sjsg 		/* runtime db doesn't exist, exit */
349f005ef32Sjsg 		dev_dbg(adev->dev, "PSP runtime database doesn't exist\n");
3505ca02815Sjsg 		return false;
3515ca02815Sjsg 	}
3525ca02815Sjsg 
3535ca02815Sjsg 	/* read runtime database entry from vram */
3545ca02815Sjsg 	amdgpu_device_vram_access(adev, db_dir_pos, (uint32_t *)&db_dir,
3555ca02815Sjsg 			sizeof(struct psp_runtime_data_directory), false);
3565ca02815Sjsg 
3575ca02815Sjsg 	if (db_dir.entry_count >= PSP_RUNTIME_DB_DIAG_ENTRY_MAX_COUNT) {
3585ca02815Sjsg 		/* invalid db entry count, exit */
3595ca02815Sjsg 		dev_warn(adev->dev, "Invalid PSP runtime database entry count\n");
3605ca02815Sjsg 		return false;
3615ca02815Sjsg 	}
3625ca02815Sjsg 
3635ca02815Sjsg 	/* look up for requested entry type */
3645ca02815Sjsg 	for (i = 0; i < db_dir.entry_count && !ret; i++) {
3655ca02815Sjsg 		if (db_dir.entry_list[i].entry_type == entry_type) {
3665ca02815Sjsg 			switch (entry_type) {
3675ca02815Sjsg 			case PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG:
3685ca02815Sjsg 				if (db_dir.entry_list[i].size < sizeof(struct psp_runtime_boot_cfg_entry)) {
3695ca02815Sjsg 					/* invalid db entry size */
3701bb76ff1Sjsg 					dev_warn(adev->dev, "Invalid PSP runtime database boot cfg entry size\n");
3715ca02815Sjsg 					return false;
3725ca02815Sjsg 				}
3735ca02815Sjsg 				/* read runtime database entry */
3745ca02815Sjsg 				amdgpu_device_vram_access(adev, db_header_pos + db_dir.entry_list[i].offset,
3755ca02815Sjsg 							  (uint32_t *)db_entry, sizeof(struct psp_runtime_boot_cfg_entry), false);
3765ca02815Sjsg 				ret = true;
3775ca02815Sjsg 				break;
3781bb76ff1Sjsg 			case PSP_RUNTIME_ENTRY_TYPE_PPTABLE_ERR_STATUS:
3791bb76ff1Sjsg 				if (db_dir.entry_list[i].size < sizeof(struct psp_runtime_scpm_entry)) {
3801bb76ff1Sjsg 					/* invalid db entry size */
3811bb76ff1Sjsg 					dev_warn(adev->dev, "Invalid PSP runtime database scpm entry size\n");
3821bb76ff1Sjsg 					return false;
3831bb76ff1Sjsg 				}
3841bb76ff1Sjsg 				/* read runtime database entry */
3851bb76ff1Sjsg 				amdgpu_device_vram_access(adev, db_header_pos + db_dir.entry_list[i].offset,
3861bb76ff1Sjsg 							  (uint32_t *)db_entry, sizeof(struct psp_runtime_scpm_entry), false);
3871bb76ff1Sjsg 				ret = true;
3881bb76ff1Sjsg 				break;
3895ca02815Sjsg 			default:
3905ca02815Sjsg 				ret = false;
3915ca02815Sjsg 				break;
3925ca02815Sjsg 			}
3935ca02815Sjsg 		}
3945ca02815Sjsg 	}
3955ca02815Sjsg 
3965ca02815Sjsg 	return ret;
3975ca02815Sjsg }
3985ca02815Sjsg 
399c8a1e887Sjsg static int psp_sw_init(void *handle)
400c8a1e887Sjsg {
401c8a1e887Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
402c8a1e887Sjsg 	struct psp_context *psp = &adev->psp;
403c8a1e887Sjsg 	int ret;
4045ca02815Sjsg 	struct psp_runtime_boot_cfg_entry boot_cfg_entry;
4055ca02815Sjsg 	struct psp_memory_training_context *mem_training_ctx = &psp->mem_train_ctx;
4061bb76ff1Sjsg 	struct psp_runtime_scpm_entry scpm_entry;
4075ca02815Sjsg 
4085ca02815Sjsg 	psp->cmd = kzalloc(sizeof(struct psp_gfx_cmd_resp), GFP_KERNEL);
4095ca02815Sjsg 	if (!psp->cmd) {
4105ca02815Sjsg 		DRM_ERROR("Failed to allocate memory to command buffer!\n");
4115ca02815Sjsg 		ret = -ENOMEM;
4125ca02815Sjsg 	}
413c8a1e887Sjsg 
4141bb76ff1Sjsg 	adev->psp.xgmi_context.supports_extended_data =
4151bb76ff1Sjsg 		!adev->gmc.xgmi.connected_to_cpu &&
4161bb76ff1Sjsg 			adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2);
4171bb76ff1Sjsg 
4181bb76ff1Sjsg 	memset(&scpm_entry, 0, sizeof(scpm_entry));
4191bb76ff1Sjsg 	if ((psp_get_runtime_db_entry(adev,
4201bb76ff1Sjsg 				PSP_RUNTIME_ENTRY_TYPE_PPTABLE_ERR_STATUS,
4211bb76ff1Sjsg 				&scpm_entry)) &&
422f005ef32Sjsg 	    (scpm_entry.scpm_status != SCPM_DISABLE)) {
4231bb76ff1Sjsg 		adev->scpm_enabled = true;
4241bb76ff1Sjsg 		adev->scpm_status = scpm_entry.scpm_status;
4251bb76ff1Sjsg 	} else {
4261bb76ff1Sjsg 		adev->scpm_enabled = false;
4271bb76ff1Sjsg 		adev->scpm_status = SCPM_DISABLE;
4285ca02815Sjsg 	}
4291bb76ff1Sjsg 
4301bb76ff1Sjsg 	/* TODO: stop gpu driver services and print alarm if scpm is enabled with error status */
431fb4d8502Sjsg 
4325ca02815Sjsg 	memset(&boot_cfg_entry, 0, sizeof(boot_cfg_entry));
4335ca02815Sjsg 	if (psp_get_runtime_db_entry(adev,
4345ca02815Sjsg 				PSP_RUNTIME_ENTRY_TYPE_BOOT_CONFIG,
4355ca02815Sjsg 				&boot_cfg_entry)) {
4365ca02815Sjsg 		psp->boot_cfg_bitmask = boot_cfg_entry.boot_cfg_bitmask;
4375ca02815Sjsg 		if ((psp->boot_cfg_bitmask) &
4385ca02815Sjsg 		    BOOT_CFG_FEATURE_TWO_STAGE_DRAM_TRAINING) {
4395ca02815Sjsg 			/* If psp runtime database exists, then
4405ca02815Sjsg 			 * only enable two stage memory training
4415ca02815Sjsg 			 * when TWO_STAGE_DRAM_TRAINING bit is set
442f005ef32Sjsg 			 * in runtime database
443f005ef32Sjsg 			 */
4445ca02815Sjsg 			mem_training_ctx->enable_mem_training = true;
4455ca02815Sjsg 		}
4465ca02815Sjsg 
4475ca02815Sjsg 	} else {
448f005ef32Sjsg 		/* If psp runtime database doesn't exist or is
449f005ef32Sjsg 		 * invalid, force enable two stage memory training
450f005ef32Sjsg 		 */
4515ca02815Sjsg 		mem_training_ctx->enable_mem_training = true;
4525ca02815Sjsg 	}
4535ca02815Sjsg 
4545ca02815Sjsg 	if (mem_training_ctx->enable_mem_training) {
455ad8b1aafSjsg 		ret = psp_memory_training_init(psp);
456c349dbc7Sjsg 		if (ret) {
457c349dbc7Sjsg 			DRM_ERROR("Failed to initialize memory training!\n");
458c349dbc7Sjsg 			return ret;
459c349dbc7Sjsg 		}
4605ca02815Sjsg 
461c349dbc7Sjsg 		ret = psp_mem_training(psp, PSP_MEM_TRAIN_COLD_BOOT);
462c349dbc7Sjsg 		if (ret) {
463c349dbc7Sjsg 			DRM_ERROR("Failed to process memory training!\n");
464c349dbc7Sjsg 			return ret;
465c349dbc7Sjsg 		}
4665ca02815Sjsg 	}
467c349dbc7Sjsg 
4680ae6e948Sjsg 	ret = amdgpu_bo_create_kernel(adev, PSP_1_MEG, PSP_1_MEG,
4690ae6e948Sjsg 				      amdgpu_sriov_vf(adev) ?
4700ae6e948Sjsg 				      AMDGPU_GEM_DOMAIN_VRAM : AMDGPU_GEM_DOMAIN_GTT,
4710ae6e948Sjsg 				      &psp->fw_pri_bo,
4720ae6e948Sjsg 				      &psp->fw_pri_mc_addr,
4730ae6e948Sjsg 				      &psp->fw_pri_buf);
4740ae6e948Sjsg 	if (ret)
4750ae6e948Sjsg 		return ret;
4760ae6e948Sjsg 
4770ae6e948Sjsg 	ret = amdgpu_bo_create_kernel(adev, PSP_FENCE_BUFFER_SIZE, PAGE_SIZE,
478f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_VRAM |
479f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_GTT,
4800ae6e948Sjsg 				      &psp->fence_buf_bo,
4810ae6e948Sjsg 				      &psp->fence_buf_mc_addr,
4820ae6e948Sjsg 				      &psp->fence_buf);
4830ae6e948Sjsg 	if (ret)
4840ae6e948Sjsg 		goto failed1;
4850ae6e948Sjsg 
4860ae6e948Sjsg 	ret = amdgpu_bo_create_kernel(adev, PSP_CMD_BUFFER_SIZE, PAGE_SIZE,
487f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_VRAM |
488f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_GTT,
4890ae6e948Sjsg 				      &psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
4900ae6e948Sjsg 				      (void **)&psp->cmd_buf_mem);
4910ae6e948Sjsg 	if (ret)
4920ae6e948Sjsg 		goto failed2;
4930ae6e948Sjsg 
494fb4d8502Sjsg 	return 0;
4950ae6e948Sjsg 
4960ae6e948Sjsg failed2:
4970ae6e948Sjsg 	amdgpu_bo_free_kernel(&psp->fence_buf_bo,
4980ae6e948Sjsg 			      &psp->fence_buf_mc_addr, &psp->fence_buf);
499c000984bSjsg failed1:
500c000984bSjsg 	amdgpu_bo_free_kernel(&psp->fw_pri_bo,
501c000984bSjsg 			      &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
5020ae6e948Sjsg 	return ret;
503fb4d8502Sjsg }
504fb4d8502Sjsg 
505fb4d8502Sjsg static int psp_sw_fini(void *handle)
506fb4d8502Sjsg {
507fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
5085ca02815Sjsg 	struct psp_context *psp = &adev->psp;
5095ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd = psp->cmd;
510fb4d8502Sjsg 
5115ca02815Sjsg 	psp_memory_training_fini(psp);
512f005ef32Sjsg 
513f005ef32Sjsg 	amdgpu_ucode_release(&psp->sos_fw);
514f005ef32Sjsg 	amdgpu_ucode_release(&psp->asd_fw);
515f005ef32Sjsg 	amdgpu_ucode_release(&psp->ta_fw);
516f005ef32Sjsg 	amdgpu_ucode_release(&psp->cap_fw);
517f005ef32Sjsg 	amdgpu_ucode_release(&psp->toc_fw);
518c349dbc7Sjsg 
5195ca02815Sjsg 	kfree(cmd);
5205ca02815Sjsg 	cmd = NULL;
5215ca02815Sjsg 
5225711e8cdSjsg 	psp_free_shared_bufs(psp);
5235711e8cdSjsg 
5241bb76ff1Sjsg 	if (psp->km_ring.ring_mem)
5251bb76ff1Sjsg 		amdgpu_bo_free_kernel(&adev->firmware.rbuf,
5261bb76ff1Sjsg 				      &psp->km_ring.ring_mem_mc_addr,
5271bb76ff1Sjsg 				      (void **)&psp->km_ring.ring_mem);
5281bb76ff1Sjsg 
5290ae6e948Sjsg 	amdgpu_bo_free_kernel(&psp->fw_pri_bo,
5300ae6e948Sjsg 			      &psp->fw_pri_mc_addr, &psp->fw_pri_buf);
5310ae6e948Sjsg 	amdgpu_bo_free_kernel(&psp->fence_buf_bo,
5320ae6e948Sjsg 			      &psp->fence_buf_mc_addr, &psp->fence_buf);
5330ae6e948Sjsg 	amdgpu_bo_free_kernel(&psp->cmd_buf_bo, &psp->cmd_buf_mc_addr,
5340ae6e948Sjsg 			      (void **)&psp->cmd_buf_mem);
5350ae6e948Sjsg 
536fb4d8502Sjsg 	return 0;
537fb4d8502Sjsg }
538fb4d8502Sjsg 
539fb4d8502Sjsg int psp_wait_for(struct psp_context *psp, uint32_t reg_index,
540fb4d8502Sjsg 		 uint32_t reg_val, uint32_t mask, bool check_changed)
541fb4d8502Sjsg {
542fb4d8502Sjsg 	uint32_t val;
543fb4d8502Sjsg 	int i;
544fb4d8502Sjsg 	struct amdgpu_device *adev = psp->adev;
545fb4d8502Sjsg 
5465ca02815Sjsg 	if (psp->adev->no_hw_access)
547ad8b1aafSjsg 		return 0;
548ad8b1aafSjsg 
549fb4d8502Sjsg 	for (i = 0; i < adev->usec_timeout; i++) {
550fb4d8502Sjsg 		val = RREG32(reg_index);
551fb4d8502Sjsg 		if (check_changed) {
552fb4d8502Sjsg 			if (val != reg_val)
553fb4d8502Sjsg 				return 0;
554fb4d8502Sjsg 		} else {
555fb4d8502Sjsg 			if ((val & mask) == reg_val)
556fb4d8502Sjsg 				return 0;
557fb4d8502Sjsg 		}
558fb4d8502Sjsg 		udelay(1);
559fb4d8502Sjsg 	}
560fb4d8502Sjsg 
561fb4d8502Sjsg 	return -ETIME;
562fb4d8502Sjsg }
563fb4d8502Sjsg 
564f005ef32Sjsg int psp_wait_for_spirom_update(struct psp_context *psp, uint32_t reg_index,
565f005ef32Sjsg 			       uint32_t reg_val, uint32_t mask, uint32_t msec_timeout)
566f005ef32Sjsg {
567f005ef32Sjsg 	uint32_t val;
568f005ef32Sjsg 	int i;
569f005ef32Sjsg 	struct amdgpu_device *adev = psp->adev;
570f005ef32Sjsg 
571f005ef32Sjsg 	if (psp->adev->no_hw_access)
572f005ef32Sjsg 		return 0;
573f005ef32Sjsg 
574f005ef32Sjsg 	for (i = 0; i < msec_timeout; i++) {
575f005ef32Sjsg 		val = RREG32(reg_index);
576f005ef32Sjsg 		if ((val & mask) == reg_val)
577f005ef32Sjsg 			return 0;
578f005ef32Sjsg 		drm_msleep(1);
579f005ef32Sjsg 	}
580f005ef32Sjsg 
581f005ef32Sjsg 	return -ETIME;
582f005ef32Sjsg }
583f005ef32Sjsg 
5845ca02815Sjsg static const char *psp_gfx_cmd_name(enum psp_gfx_cmd_id cmd_id)
5855ca02815Sjsg {
5865ca02815Sjsg 	switch (cmd_id) {
5875ca02815Sjsg 	case GFX_CMD_ID_LOAD_TA:
5885ca02815Sjsg 		return "LOAD_TA";
5895ca02815Sjsg 	case GFX_CMD_ID_UNLOAD_TA:
5905ca02815Sjsg 		return "UNLOAD_TA";
5915ca02815Sjsg 	case GFX_CMD_ID_INVOKE_CMD:
5925ca02815Sjsg 		return "INVOKE_CMD";
5935ca02815Sjsg 	case GFX_CMD_ID_LOAD_ASD:
5945ca02815Sjsg 		return "LOAD_ASD";
5955ca02815Sjsg 	case GFX_CMD_ID_SETUP_TMR:
5965ca02815Sjsg 		return "SETUP_TMR";
5975ca02815Sjsg 	case GFX_CMD_ID_LOAD_IP_FW:
5985ca02815Sjsg 		return "LOAD_IP_FW";
5995ca02815Sjsg 	case GFX_CMD_ID_DESTROY_TMR:
6005ca02815Sjsg 		return "DESTROY_TMR";
6015ca02815Sjsg 	case GFX_CMD_ID_SAVE_RESTORE:
6025ca02815Sjsg 		return "SAVE_RESTORE_IP_FW";
6035ca02815Sjsg 	case GFX_CMD_ID_SETUP_VMR:
6045ca02815Sjsg 		return "SETUP_VMR";
6055ca02815Sjsg 	case GFX_CMD_ID_DESTROY_VMR:
6065ca02815Sjsg 		return "DESTROY_VMR";
6075ca02815Sjsg 	case GFX_CMD_ID_PROG_REG:
6085ca02815Sjsg 		return "PROG_REG";
6095ca02815Sjsg 	case GFX_CMD_ID_GET_FW_ATTESTATION:
6105ca02815Sjsg 		return "GET_FW_ATTESTATION";
6115ca02815Sjsg 	case GFX_CMD_ID_LOAD_TOC:
6125ca02815Sjsg 		return "ID_LOAD_TOC";
6135ca02815Sjsg 	case GFX_CMD_ID_AUTOLOAD_RLC:
6145ca02815Sjsg 		return "AUTOLOAD_RLC";
6155ca02815Sjsg 	case GFX_CMD_ID_BOOT_CFG:
6165ca02815Sjsg 		return "BOOT_CFG";
6175ca02815Sjsg 	default:
6185ca02815Sjsg 		return "UNKNOWN CMD";
6195ca02815Sjsg 	}
6205ca02815Sjsg }
6215ca02815Sjsg 
622fb4d8502Sjsg static int
623fb4d8502Sjsg psp_cmd_submit_buf(struct psp_context *psp,
624fb4d8502Sjsg 		   struct amdgpu_firmware_info *ucode,
625c349dbc7Sjsg 		   struct psp_gfx_cmd_resp *cmd, uint64_t fence_mc_addr)
626fb4d8502Sjsg {
627fb4d8502Sjsg 	int ret;
628f005ef32Sjsg 	int index;
6295ca02815Sjsg 	int timeout = 20000;
630c349dbc7Sjsg 	bool ras_intr = false;
631ad8b1aafSjsg 	bool skip_unsupport = false;
632ad8b1aafSjsg 
6335ca02815Sjsg 	if (psp->adev->no_hw_access)
634ad8b1aafSjsg 		return 0;
635c349dbc7Sjsg 
636fb4d8502Sjsg 	memset(psp->cmd_buf_mem, 0, PSP_CMD_BUFFER_SIZE);
637fb4d8502Sjsg 
638fb4d8502Sjsg 	memcpy(psp->cmd_buf_mem, cmd, sizeof(struct psp_gfx_cmd_resp));
639fb4d8502Sjsg 
640c349dbc7Sjsg 	index = atomic_inc_return(&psp->fence_value);
641c349dbc7Sjsg 	ret = psp_ring_cmd_submit(psp, psp->cmd_buf_mc_addr, fence_mc_addr, index);
642c349dbc7Sjsg 	if (ret) {
643c349dbc7Sjsg 		atomic_dec(&psp->fence_value);
6445ca02815Sjsg 		goto exit;
645fb4d8502Sjsg 	}
646fb4d8502Sjsg 
6475ca02815Sjsg 	amdgpu_device_invalidate_hdp(psp->adev, NULL);
648c349dbc7Sjsg 	while (*((unsigned int *)psp->fence_buf) != index) {
649c349dbc7Sjsg 		if (--timeout == 0)
650c349dbc7Sjsg 			break;
651c349dbc7Sjsg 		/*
652c349dbc7Sjsg 		 * Shouldn't wait for timeout when err_event_athub occurs,
653c349dbc7Sjsg 		 * because gpu reset thread triggered and lock resource should
654c349dbc7Sjsg 		 * be released for psp resume sequence.
655c349dbc7Sjsg 		 */
656c349dbc7Sjsg 		ras_intr = amdgpu_ras_intr_triggered();
657c349dbc7Sjsg 		if (ras_intr)
658c349dbc7Sjsg 			break;
6595ca02815Sjsg 		usleep_range(10, 100);
6605ca02815Sjsg 		amdgpu_device_invalidate_hdp(psp->adev, NULL);
661c349dbc7Sjsg 	}
662c349dbc7Sjsg 
663ad8b1aafSjsg 	/* We allow TEE_ERROR_NOT_SUPPORTED for VMR command and PSP_ERR_UNKNOWN_COMMAND in SRIOV */
664ad8b1aafSjsg 	skip_unsupport = (psp->cmd_buf_mem->resp.status == TEE_ERROR_NOT_SUPPORTED ||
665ad8b1aafSjsg 		psp->cmd_buf_mem->resp.status == PSP_ERR_UNKNOWN_COMMAND) && amdgpu_sriov_vf(psp->adev);
666ad8b1aafSjsg 
667f005ef32Sjsg 	memcpy(&cmd->resp, &psp->cmd_buf_mem->resp, sizeof(struct psp_gfx_resp));
6685ca02815Sjsg 
669c349dbc7Sjsg 	/* In some cases, psp response status is not 0 even there is no
670c349dbc7Sjsg 	 * problem while the command is submitted. Some version of PSP FW
671c349dbc7Sjsg 	 * doesn't write 0 to that field.
672c349dbc7Sjsg 	 * So here we would like to only print a warning instead of an error
673c349dbc7Sjsg 	 * during psp initialization to avoid breaking hw_init and it doesn't
674c349dbc7Sjsg 	 * return -EINVAL.
675c349dbc7Sjsg 	 */
676ad8b1aafSjsg 	if (!skip_unsupport && (psp->cmd_buf_mem->resp.status || !timeout) && !ras_intr) {
677c349dbc7Sjsg 		if (ucode)
6785ca02815Sjsg 			DRM_WARN("failed to load ucode %s(0x%X) ",
6795ca02815Sjsg 				  amdgpu_ucode_name(ucode->ucode_id), ucode->ucode_id);
6805ca02815Sjsg 		DRM_WARN("psp gfx command %s(0x%X) failed and response status is (0x%X)\n",
6815ca02815Sjsg 			 psp_gfx_cmd_name(psp->cmd_buf_mem->cmd_id), psp->cmd_buf_mem->cmd_id,
682c349dbc7Sjsg 			 psp->cmd_buf_mem->resp.status);
6831bb76ff1Sjsg 		/* If any firmware (including CAP) load fails under SRIOV, it should
6841bb76ff1Sjsg 		 * return failure to stop the VF from initializing.
6851bb76ff1Sjsg 		 * Also return failure in case of timeout
6861bb76ff1Sjsg 		 */
6871bb76ff1Sjsg 		if ((ucode && amdgpu_sriov_vf(psp->adev)) || !timeout) {
6885ca02815Sjsg 			ret = -EINVAL;
6895ca02815Sjsg 			goto exit;
690c349dbc7Sjsg 		}
691c349dbc7Sjsg 	}
692c349dbc7Sjsg 
693fb4d8502Sjsg 	if (ucode) {
694fb4d8502Sjsg 		ucode->tmr_mc_addr_lo = psp->cmd_buf_mem->resp.fw_addr_lo;
695fb4d8502Sjsg 		ucode->tmr_mc_addr_hi = psp->cmd_buf_mem->resp.fw_addr_hi;
696fb4d8502Sjsg 	}
697fb4d8502Sjsg 
6985ca02815Sjsg exit:
699fb4d8502Sjsg 	return ret;
700fb4d8502Sjsg }
701fb4d8502Sjsg 
7025ca02815Sjsg static struct psp_gfx_cmd_resp *acquire_psp_cmd_buf(struct psp_context *psp)
7035ca02815Sjsg {
7045ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd = psp->cmd;
7055ca02815Sjsg 
7065ca02815Sjsg 	mutex_lock(&psp->mutex);
7075ca02815Sjsg 
7085ca02815Sjsg 	memset(cmd, 0, sizeof(struct psp_gfx_cmd_resp));
7095ca02815Sjsg 
7105ca02815Sjsg 	return cmd;
7115ca02815Sjsg }
7125ca02815Sjsg 
7131bb76ff1Sjsg static void release_psp_cmd_buf(struct psp_context *psp)
7145ca02815Sjsg {
7155ca02815Sjsg 	mutex_unlock(&psp->mutex);
7165ca02815Sjsg }
7175ca02815Sjsg 
718c349dbc7Sjsg static void psp_prep_tmr_cmd_buf(struct psp_context *psp,
719c349dbc7Sjsg 				 struct psp_gfx_cmd_resp *cmd,
7205ca02815Sjsg 				 uint64_t tmr_mc, struct amdgpu_bo *tmr_bo)
721fb4d8502Sjsg {
7225ca02815Sjsg 	struct amdgpu_device *adev = psp->adev;
723f005ef32Sjsg 	uint32_t size = 0;
724f005ef32Sjsg 	uint64_t tmr_pa = 0;
725f005ef32Sjsg 
726f005ef32Sjsg 	if (tmr_bo) {
727f005ef32Sjsg 		size = amdgpu_bo_size(tmr_bo);
728f005ef32Sjsg 		tmr_pa = amdgpu_gmc_vram_pa(adev, tmr_bo);
729f005ef32Sjsg 	}
7305ca02815Sjsg 
731ad8b1aafSjsg 	if (amdgpu_sriov_vf(psp->adev))
732c349dbc7Sjsg 		cmd->cmd_id = GFX_CMD_ID_SETUP_VMR;
733c349dbc7Sjsg 	else
734fb4d8502Sjsg 		cmd->cmd_id = GFX_CMD_ID_SETUP_TMR;
735fb4d8502Sjsg 	cmd->cmd.cmd_setup_tmr.buf_phy_addr_lo = lower_32_bits(tmr_mc);
736fb4d8502Sjsg 	cmd->cmd.cmd_setup_tmr.buf_phy_addr_hi = upper_32_bits(tmr_mc);
737fb4d8502Sjsg 	cmd->cmd.cmd_setup_tmr.buf_size = size;
7385ca02815Sjsg 	cmd->cmd.cmd_setup_tmr.bitfield.virt_phy_addr = 1;
7395ca02815Sjsg 	cmd->cmd.cmd_setup_tmr.system_phy_addr_lo = lower_32_bits(tmr_pa);
7405ca02815Sjsg 	cmd->cmd.cmd_setup_tmr.system_phy_addr_hi = upper_32_bits(tmr_pa);
741fb4d8502Sjsg }
742fb4d8502Sjsg 
743c349dbc7Sjsg static void psp_prep_load_toc_cmd_buf(struct psp_gfx_cmd_resp *cmd,
744c349dbc7Sjsg 				      uint64_t pri_buf_mc, uint32_t size)
745c349dbc7Sjsg {
746c349dbc7Sjsg 	cmd->cmd_id = GFX_CMD_ID_LOAD_TOC;
747c349dbc7Sjsg 	cmd->cmd.cmd_load_toc.toc_phy_addr_lo = lower_32_bits(pri_buf_mc);
748c349dbc7Sjsg 	cmd->cmd.cmd_load_toc.toc_phy_addr_hi = upper_32_bits(pri_buf_mc);
749c349dbc7Sjsg 	cmd->cmd.cmd_load_toc.toc_size = size;
750c349dbc7Sjsg }
751c349dbc7Sjsg 
752c349dbc7Sjsg /* Issue LOAD TOC cmd to PSP to part toc and calculate tmr size needed */
753c349dbc7Sjsg static int psp_load_toc(struct psp_context *psp,
754c349dbc7Sjsg 			uint32_t *tmr_size)
755c349dbc7Sjsg {
756c349dbc7Sjsg 	int ret;
7575ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
758c349dbc7Sjsg 
759c349dbc7Sjsg 	/* Copy toc to psp firmware private buffer */
7605ca02815Sjsg 	psp_copy_fw(psp, psp->toc.start_addr, psp->toc.size_bytes);
761c349dbc7Sjsg 
7625ca02815Sjsg 	psp_prep_load_toc_cmd_buf(cmd, psp->fw_pri_mc_addr, psp->toc.size_bytes);
763c349dbc7Sjsg 
764c349dbc7Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
765c349dbc7Sjsg 				 psp->fence_buf_mc_addr);
766c349dbc7Sjsg 	if (!ret)
767c349dbc7Sjsg 		*tmr_size = psp->cmd_buf_mem->resp.tmr_size;
7685ca02815Sjsg 
7695ca02815Sjsg 	release_psp_cmd_buf(psp);
7705ca02815Sjsg 
771c349dbc7Sjsg 	return ret;
772c349dbc7Sjsg }
773c349dbc7Sjsg 
774f005ef32Sjsg static bool psp_boottime_tmr(struct psp_context *psp)
775f005ef32Sjsg {
776f005ef32Sjsg 	switch (psp->adev->ip_versions[MP0_HWIP][0]) {
777f005ef32Sjsg 	case IP_VERSION(13, 0, 6):
778f005ef32Sjsg 		return true;
779f005ef32Sjsg 	default:
780f005ef32Sjsg 		return false;
781f005ef32Sjsg 	}
782f005ef32Sjsg }
783f005ef32Sjsg 
784fb4d8502Sjsg /* Set up Trusted Memory Region */
785fb4d8502Sjsg static int psp_tmr_init(struct psp_context *psp)
786fb4d8502Sjsg {
7871bb76ff1Sjsg 	int ret = 0;
788c349dbc7Sjsg 	int tmr_size;
789c349dbc7Sjsg 	void *tmr_buf;
790c349dbc7Sjsg 	void **pptr;
791fb4d8502Sjsg 
792fb4d8502Sjsg 	/*
793c349dbc7Sjsg 	 * According to HW engineer, they prefer the TMR address be "naturally
794c349dbc7Sjsg 	 * aligned" , e.g. the start address be an integer divide of TMR size.
795fb4d8502Sjsg 	 *
796fb4d8502Sjsg 	 * Note: this memory need be reserved till the driver
797fb4d8502Sjsg 	 * uninitializes.
798fb4d8502Sjsg 	 */
7995ca02815Sjsg 	tmr_size = PSP_TMR_SIZE(psp->adev);
800c349dbc7Sjsg 
801c349dbc7Sjsg 	/* For ASICs support RLC autoload, psp will parse the toc
802f005ef32Sjsg 	 * and calculate the total size of TMR needed
803f005ef32Sjsg 	 */
804c349dbc7Sjsg 	if (!amdgpu_sriov_vf(psp->adev) &&
8055ca02815Sjsg 	    psp->toc.start_addr &&
8065ca02815Sjsg 	    psp->toc.size_bytes &&
807c349dbc7Sjsg 	    psp->fw_pri_buf) {
808c349dbc7Sjsg 		ret = psp_load_toc(psp, &tmr_size);
809c349dbc7Sjsg 		if (ret) {
810c349dbc7Sjsg 			DRM_ERROR("Failed to load toc\n");
811c349dbc7Sjsg 			return ret;
812c349dbc7Sjsg 		}
813c349dbc7Sjsg 	}
814c349dbc7Sjsg 
8151bb76ff1Sjsg 	if (!psp->tmr_bo) {
816c349dbc7Sjsg 		pptr = amdgpu_sriov_vf(psp->adev) ? &tmr_buf : NULL;
817f005ef32Sjsg 		ret = amdgpu_bo_create_kernel(psp->adev, tmr_size,
818f005ef32Sjsg 					      PSP_TMR_ALIGNMENT,
819f005ef32Sjsg 					      AMDGPU_HAS_VRAM(psp->adev) ?
820f005ef32Sjsg 					      AMDGPU_GEM_DOMAIN_VRAM :
821f005ef32Sjsg 					      AMDGPU_GEM_DOMAIN_GTT,
822f005ef32Sjsg 					      &psp->tmr_bo, &psp->tmr_mc_addr,
823f005ef32Sjsg 					      pptr);
8241bb76ff1Sjsg 	}
825fb4d8502Sjsg 
826fb4d8502Sjsg 	return ret;
827fb4d8502Sjsg }
828fb4d8502Sjsg 
829ad8b1aafSjsg static bool psp_skip_tmr(struct psp_context *psp)
830ad8b1aafSjsg {
8311bb76ff1Sjsg 	switch (psp->adev->ip_versions[MP0_HWIP][0]) {
8321bb76ff1Sjsg 	case IP_VERSION(11, 0, 9):
8331bb76ff1Sjsg 	case IP_VERSION(11, 0, 7):
8341bb76ff1Sjsg 	case IP_VERSION(13, 0, 2):
835f005ef32Sjsg 	case IP_VERSION(13, 0, 6):
8361bb76ff1Sjsg 	case IP_VERSION(13, 0, 10):
837ad8b1aafSjsg 		return true;
838ad8b1aafSjsg 	default:
839ad8b1aafSjsg 		return false;
840ad8b1aafSjsg 	}
841ad8b1aafSjsg }
842ad8b1aafSjsg 
843fb4d8502Sjsg static int psp_tmr_load(struct psp_context *psp)
844fb4d8502Sjsg {
845fb4d8502Sjsg 	int ret;
846fb4d8502Sjsg 	struct psp_gfx_cmd_resp *cmd;
847fb4d8502Sjsg 
848ad8b1aafSjsg 	/* For Navi12 and CHIP_SIENNA_CICHLID SRIOV, do not set up TMR.
849ad8b1aafSjsg 	 * Already set up by host driver.
850ad8b1aafSjsg 	 */
851ad8b1aafSjsg 	if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp))
852ad8b1aafSjsg 		return 0;
853ad8b1aafSjsg 
8545ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
855fb4d8502Sjsg 
8565ca02815Sjsg 	psp_prep_tmr_cmd_buf(psp, cmd, psp->tmr_mc_addr, psp->tmr_bo);
857f005ef32Sjsg 	if (psp->tmr_bo)
858c349dbc7Sjsg 		DRM_INFO("reserve 0x%lx from 0x%llx for PSP TMR\n",
859c349dbc7Sjsg 			 amdgpu_bo_size(psp->tmr_bo), psp->tmr_mc_addr);
860fb4d8502Sjsg 
861fb4d8502Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
862c349dbc7Sjsg 				 psp->fence_buf_mc_addr);
863fb4d8502Sjsg 
8645ca02815Sjsg 	release_psp_cmd_buf(psp);
865fb4d8502Sjsg 
866fb4d8502Sjsg 	return ret;
867fb4d8502Sjsg }
868fb4d8502Sjsg 
8696bd9a77dSjsg static void psp_prep_tmr_unload_cmd_buf(struct psp_context *psp,
8706bd9a77dSjsg 					struct psp_gfx_cmd_resp *cmd)
8716bd9a77dSjsg {
8726bd9a77dSjsg 	if (amdgpu_sriov_vf(psp->adev))
8736bd9a77dSjsg 		cmd->cmd_id = GFX_CMD_ID_DESTROY_VMR;
8746bd9a77dSjsg 	else
8756bd9a77dSjsg 		cmd->cmd_id = GFX_CMD_ID_DESTROY_TMR;
8766bd9a77dSjsg }
8776bd9a77dSjsg 
8786bd9a77dSjsg static int psp_tmr_unload(struct psp_context *psp)
8796bd9a77dSjsg {
8806bd9a77dSjsg 	int ret;
881f005ef32Sjsg 	struct psp_gfx_cmd_resp *cmd;
882f005ef32Sjsg 
883f005ef32Sjsg 	/* skip TMR unload for Navi12 and CHIP_SIENNA_CICHLID SRIOV,
884f005ef32Sjsg 	 * as TMR is not loaded at all
885f005ef32Sjsg 	 */
886f005ef32Sjsg 	if (amdgpu_sriov_vf(psp->adev) && psp_skip_tmr(psp))
887f005ef32Sjsg 		return 0;
888f005ef32Sjsg 
889f005ef32Sjsg 	cmd = acquire_psp_cmd_buf(psp);
8906bd9a77dSjsg 
8916bd9a77dSjsg 	psp_prep_tmr_unload_cmd_buf(psp, cmd);
892f005ef32Sjsg 	dev_dbg(psp->adev->dev, "free PSP TMR buffer\n");
8936bd9a77dSjsg 
8946bd9a77dSjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
8956bd9a77dSjsg 				 psp->fence_buf_mc_addr);
8966bd9a77dSjsg 
8975ca02815Sjsg 	release_psp_cmd_buf(psp);
8986bd9a77dSjsg 
8996bd9a77dSjsg 	return ret;
9006bd9a77dSjsg }
9016bd9a77dSjsg 
9026bd9a77dSjsg static int psp_tmr_terminate(struct psp_context *psp)
9036bd9a77dSjsg {
9041bb76ff1Sjsg 	return psp_tmr_unload(psp);
9056bd9a77dSjsg }
9066bd9a77dSjsg 
9075ca02815Sjsg int psp_get_fw_attestation_records_addr(struct psp_context *psp,
9085ca02815Sjsg 					uint64_t *output_ptr)
9095ca02815Sjsg {
9105ca02815Sjsg 	int ret;
9115ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd;
9125ca02815Sjsg 
9135ca02815Sjsg 	if (!output_ptr)
9145ca02815Sjsg 		return -EINVAL;
9155ca02815Sjsg 
9165ca02815Sjsg 	if (amdgpu_sriov_vf(psp->adev))
9175ca02815Sjsg 		return 0;
9185ca02815Sjsg 
9195ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
9205ca02815Sjsg 
9215ca02815Sjsg 	cmd->cmd_id = GFX_CMD_ID_GET_FW_ATTESTATION;
9225ca02815Sjsg 
9235ca02815Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
9245ca02815Sjsg 				 psp->fence_buf_mc_addr);
9255ca02815Sjsg 
9265ca02815Sjsg 	if (!ret) {
9275ca02815Sjsg 		*output_ptr = ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_lo) +
9285ca02815Sjsg 			      ((uint64_t)cmd->resp.uresp.fwar_db_info.fwar_db_addr_hi << 32);
9295ca02815Sjsg 	}
9305ca02815Sjsg 
9315ca02815Sjsg 	release_psp_cmd_buf(psp);
9325ca02815Sjsg 
9335ca02815Sjsg 	return ret;
9345ca02815Sjsg }
9355ca02815Sjsg 
9365ca02815Sjsg static int psp_boot_config_get(struct amdgpu_device *adev, uint32_t *boot_cfg)
9375ca02815Sjsg {
9385ca02815Sjsg 	struct psp_context *psp = &adev->psp;
9395ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd;
9405ca02815Sjsg 	int ret;
9415ca02815Sjsg 
9425ca02815Sjsg 	if (amdgpu_sriov_vf(adev))
9435ca02815Sjsg 		return 0;
9445ca02815Sjsg 
9455ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
9465ca02815Sjsg 
9475ca02815Sjsg 	cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
9485ca02815Sjsg 	cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_GET;
9495ca02815Sjsg 
9505ca02815Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
9515ca02815Sjsg 	if (!ret) {
9525ca02815Sjsg 		*boot_cfg =
9535ca02815Sjsg 			(cmd->resp.uresp.boot_cfg.boot_cfg & BOOT_CONFIG_GECC) ? 1 : 0;
9545ca02815Sjsg 	}
9555ca02815Sjsg 
9565ca02815Sjsg 	release_psp_cmd_buf(psp);
9575ca02815Sjsg 
9585ca02815Sjsg 	return ret;
9595ca02815Sjsg }
9605ca02815Sjsg 
9615ca02815Sjsg static int psp_boot_config_set(struct amdgpu_device *adev, uint32_t boot_cfg)
9625ca02815Sjsg {
9635ca02815Sjsg 	int ret;
9645ca02815Sjsg 	struct psp_context *psp = &adev->psp;
9655ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd;
9665ca02815Sjsg 
9675ca02815Sjsg 	if (amdgpu_sriov_vf(adev))
9685ca02815Sjsg 		return 0;
9695ca02815Sjsg 
9705ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
9715ca02815Sjsg 
9725ca02815Sjsg 	cmd->cmd_id = GFX_CMD_ID_BOOT_CFG;
9735ca02815Sjsg 	cmd->cmd.boot_cfg.sub_cmd = BOOTCFG_CMD_SET;
9745ca02815Sjsg 	cmd->cmd.boot_cfg.boot_config = boot_cfg;
9755ca02815Sjsg 	cmd->cmd.boot_cfg.boot_config_valid = boot_cfg;
9765ca02815Sjsg 
9775ca02815Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
9785ca02815Sjsg 
9795ca02815Sjsg 	release_psp_cmd_buf(psp);
9805ca02815Sjsg 
9815ca02815Sjsg 	return ret;
9825ca02815Sjsg }
9835ca02815Sjsg 
9845ca02815Sjsg static int psp_rl_load(struct amdgpu_device *adev)
9855ca02815Sjsg {
9865ca02815Sjsg 	int ret;
9875ca02815Sjsg 	struct psp_context *psp = &adev->psp;
9885ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd;
9895ca02815Sjsg 
9905ca02815Sjsg 	if (!is_psp_fw_valid(psp->rl))
9915ca02815Sjsg 		return 0;
9925ca02815Sjsg 
9935ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
9945ca02815Sjsg 
9955ca02815Sjsg 	memset(psp->fw_pri_buf, 0, PSP_1_MEG);
9965ca02815Sjsg 	memcpy(psp->fw_pri_buf, psp->rl.start_addr, psp->rl.size_bytes);
9975ca02815Sjsg 
9985ca02815Sjsg 	cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
9995ca02815Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(psp->fw_pri_mc_addr);
10005ca02815Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(psp->fw_pri_mc_addr);
10015ca02815Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_size = psp->rl.size_bytes;
10025ca02815Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_type = GFX_FW_TYPE_REG_LIST;
10035ca02815Sjsg 
10045ca02815Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
10055ca02815Sjsg 
10065ca02815Sjsg 	release_psp_cmd_buf(psp);
10075ca02815Sjsg 
10085ca02815Sjsg 	return ret;
10095ca02815Sjsg }
10105ca02815Sjsg 
1011f005ef32Sjsg int psp_spatial_partition(struct psp_context *psp, int mode)
1012f005ef32Sjsg {
1013f005ef32Sjsg 	struct psp_gfx_cmd_resp *cmd;
1014f005ef32Sjsg 	int ret;
1015f005ef32Sjsg 
1016f005ef32Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1017f005ef32Sjsg 		return 0;
1018f005ef32Sjsg 
1019f005ef32Sjsg 	cmd = acquire_psp_cmd_buf(psp);
1020f005ef32Sjsg 
1021f005ef32Sjsg 	cmd->cmd_id = GFX_CMD_ID_SRIOV_SPATIAL_PART;
1022f005ef32Sjsg 	cmd->cmd.cmd_spatial_part.mode = mode;
1023f005ef32Sjsg 
1024f005ef32Sjsg 	dev_info(psp->adev->dev, "Requesting %d partitions through PSP", mode);
1025f005ef32Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
1026f005ef32Sjsg 
1027f005ef32Sjsg 	release_psp_cmd_buf(psp);
1028f005ef32Sjsg 
1029f005ef32Sjsg 	return ret;
1030f005ef32Sjsg }
1031f005ef32Sjsg 
10321bb76ff1Sjsg static int psp_asd_initialize(struct psp_context *psp)
1033fb4d8502Sjsg {
1034fb4d8502Sjsg 	int ret;
1035fb4d8502Sjsg 
1036fb4d8502Sjsg 	/* If PSP version doesn't match ASD version, asd loading will be failed.
1037fb4d8502Sjsg 	 * add workaround to bypass it for sriov now.
1038fb4d8502Sjsg 	 * TODO: add version check to make it common
1039fb4d8502Sjsg 	 */
10401bb76ff1Sjsg 	if (amdgpu_sriov_vf(psp->adev) || !psp->asd_context.bin_desc.size_bytes)
1041fb4d8502Sjsg 		return 0;
1042fb4d8502Sjsg 
10431bb76ff1Sjsg 	psp->asd_context.mem_context.shared_mc_addr  = 0;
10441bb76ff1Sjsg 	psp->asd_context.mem_context.shared_mem_size = PSP_ASD_SHARED_MEM_SIZE;
10451bb76ff1Sjsg 	psp->asd_context.ta_load_type                = GFX_CMD_ID_LOAD_ASD;
1046fb4d8502Sjsg 
10471bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->asd_context);
10481bb76ff1Sjsg 	if (!ret)
10491bb76ff1Sjsg 		psp->asd_context.initialized = true;
1050fb4d8502Sjsg 
1051fb4d8502Sjsg 	return ret;
1052fb4d8502Sjsg }
1053fb4d8502Sjsg 
1054c349dbc7Sjsg static void psp_prep_ta_unload_cmd_buf(struct psp_gfx_cmd_resp *cmd,
1055c349dbc7Sjsg 				       uint32_t session_id)
1056c349dbc7Sjsg {
1057c349dbc7Sjsg 	cmd->cmd_id = GFX_CMD_ID_UNLOAD_TA;
1058c349dbc7Sjsg 	cmd->cmd.cmd_unload_ta.session_id = session_id;
1059c349dbc7Sjsg }
1060c349dbc7Sjsg 
10611bb76ff1Sjsg int psp_ta_unload(struct psp_context *psp, struct ta_context *context)
1062c349dbc7Sjsg {
1063c349dbc7Sjsg 	int ret;
10641bb76ff1Sjsg 	struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
10651bb76ff1Sjsg 
10661bb76ff1Sjsg 	psp_prep_ta_unload_cmd_buf(cmd, context->session_id);
10671bb76ff1Sjsg 
10681bb76ff1Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
10691bb76ff1Sjsg 
1070f005ef32Sjsg 	context->resp_status = cmd->resp.status;
1071f005ef32Sjsg 
10721bb76ff1Sjsg 	release_psp_cmd_buf(psp);
10731bb76ff1Sjsg 
10741bb76ff1Sjsg 	return ret;
10751bb76ff1Sjsg }
10761bb76ff1Sjsg 
10771bb76ff1Sjsg static int psp_asd_terminate(struct psp_context *psp)
10781bb76ff1Sjsg {
10791bb76ff1Sjsg 	int ret;
1080c349dbc7Sjsg 
1081c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1082c349dbc7Sjsg 		return 0;
1083c349dbc7Sjsg 
10841bb76ff1Sjsg 	if (!psp->asd_context.initialized)
1085c349dbc7Sjsg 		return 0;
1086c349dbc7Sjsg 
10871bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->asd_context);
1088c349dbc7Sjsg 	if (!ret)
10891bb76ff1Sjsg 		psp->asd_context.initialized = false;
1090c349dbc7Sjsg 
1091c349dbc7Sjsg 	return ret;
1092c349dbc7Sjsg }
1093c349dbc7Sjsg 
1094c349dbc7Sjsg static void psp_prep_reg_prog_cmd_buf(struct psp_gfx_cmd_resp *cmd,
1095c349dbc7Sjsg 		uint32_t id, uint32_t value)
1096c349dbc7Sjsg {
1097c349dbc7Sjsg 	cmd->cmd_id = GFX_CMD_ID_PROG_REG;
1098c349dbc7Sjsg 	cmd->cmd.cmd_setup_reg_prog.reg_value = value;
1099c349dbc7Sjsg 	cmd->cmd.cmd_setup_reg_prog.reg_id = id;
1100c349dbc7Sjsg }
1101c349dbc7Sjsg 
1102c349dbc7Sjsg int psp_reg_program(struct psp_context *psp, enum psp_reg_prog_id reg,
1103c349dbc7Sjsg 		uint32_t value)
1104c349dbc7Sjsg {
11055ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd;
1106c349dbc7Sjsg 	int ret = 0;
1107c349dbc7Sjsg 
1108c349dbc7Sjsg 	if (reg >= PSP_REG_LAST)
1109c349dbc7Sjsg 		return -EINVAL;
1110c349dbc7Sjsg 
11115ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
1112c349dbc7Sjsg 
1113c349dbc7Sjsg 	psp_prep_reg_prog_cmd_buf(cmd, reg, value);
1114c349dbc7Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd, psp->fence_buf_mc_addr);
11155ca02815Sjsg 	if (ret)
11165ca02815Sjsg 		DRM_ERROR("PSP failed to program reg id %d", reg);
1117c349dbc7Sjsg 
11185ca02815Sjsg 	release_psp_cmd_buf(psp);
11195ca02815Sjsg 
1120c349dbc7Sjsg 	return ret;
1121c349dbc7Sjsg }
1122c349dbc7Sjsg 
1123c349dbc7Sjsg static void psp_prep_ta_load_cmd_buf(struct psp_gfx_cmd_resp *cmd,
1124c349dbc7Sjsg 				     uint64_t ta_bin_mc,
11251bb76ff1Sjsg 				     struct ta_context *context)
1126c349dbc7Sjsg {
11271bb76ff1Sjsg 	cmd->cmd_id				= context->ta_load_type;
1128c349dbc7Sjsg 	cmd->cmd.cmd_load_ta.app_phy_addr_lo	= lower_32_bits(ta_bin_mc);
1129c349dbc7Sjsg 	cmd->cmd.cmd_load_ta.app_phy_addr_hi	= upper_32_bits(ta_bin_mc);
11301bb76ff1Sjsg 	cmd->cmd.cmd_load_ta.app_len		= context->bin_desc.size_bytes;
1131c349dbc7Sjsg 
11321bb76ff1Sjsg 	cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_lo =
11331bb76ff1Sjsg 		lower_32_bits(context->mem_context.shared_mc_addr);
11341bb76ff1Sjsg 	cmd->cmd.cmd_load_ta.cmd_buf_phy_addr_hi =
11351bb76ff1Sjsg 		upper_32_bits(context->mem_context.shared_mc_addr);
11361bb76ff1Sjsg 	cmd->cmd.cmd_load_ta.cmd_buf_len = context->mem_context.shared_mem_size;
1137c349dbc7Sjsg }
1138c349dbc7Sjsg 
11391bb76ff1Sjsg int psp_ta_init_shared_buf(struct psp_context *psp,
11401bb76ff1Sjsg 				  struct ta_mem_context *mem_ctx)
1141c349dbc7Sjsg {
1142c349dbc7Sjsg 	/*
1143c349dbc7Sjsg 	 * Allocate 16k memory aligned to 4k from Frame Buffer (local
11445ca02815Sjsg 	 * physical) for ta to host memory
1145c349dbc7Sjsg 	 */
11461bb76ff1Sjsg 	return amdgpu_bo_create_kernel(psp->adev, mem_ctx->shared_mem_size,
1147f005ef32Sjsg 				      PAGE_SIZE, AMDGPU_GEM_DOMAIN_VRAM |
1148f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_GTT,
11495ca02815Sjsg 				      &mem_ctx->shared_bo,
11505ca02815Sjsg 				      &mem_ctx->shared_mc_addr,
11515ca02815Sjsg 				      &mem_ctx->shared_buf);
11521bb76ff1Sjsg }
11531bb76ff1Sjsg 
1154c349dbc7Sjsg static void psp_prep_ta_invoke_cmd_buf(struct psp_gfx_cmd_resp *cmd,
1155c349dbc7Sjsg 				       uint32_t ta_cmd_id,
1156c349dbc7Sjsg 				       uint32_t session_id)
1157c349dbc7Sjsg {
1158c349dbc7Sjsg 	cmd->cmd_id				= GFX_CMD_ID_INVOKE_CMD;
1159c349dbc7Sjsg 	cmd->cmd.cmd_invoke_cmd.session_id	= session_id;
1160c349dbc7Sjsg 	cmd->cmd.cmd_invoke_cmd.ta_cmd_id	= ta_cmd_id;
1161c349dbc7Sjsg }
1162c349dbc7Sjsg 
11631bb76ff1Sjsg int psp_ta_invoke(struct psp_context *psp,
1164c349dbc7Sjsg 		  uint32_t ta_cmd_id,
11651bb76ff1Sjsg 		  struct ta_context *context)
1166c349dbc7Sjsg {
1167c349dbc7Sjsg 	int ret;
11685ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
1169c349dbc7Sjsg 
11701bb76ff1Sjsg 	psp_prep_ta_invoke_cmd_buf(cmd, ta_cmd_id, context->session_id);
1171c349dbc7Sjsg 
1172c349dbc7Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
1173c349dbc7Sjsg 				 psp->fence_buf_mc_addr);
1174c349dbc7Sjsg 
11751bb76ff1Sjsg 	context->resp_status = cmd->resp.status;
11761bb76ff1Sjsg 
11775ca02815Sjsg 	release_psp_cmd_buf(psp);
1178c349dbc7Sjsg 
1179c349dbc7Sjsg 	return ret;
1180c349dbc7Sjsg }
1181c349dbc7Sjsg 
11821bb76ff1Sjsg int psp_ta_load(struct psp_context *psp, struct ta_context *context)
1183c349dbc7Sjsg {
1184c349dbc7Sjsg 	int ret;
1185c349dbc7Sjsg 	struct psp_gfx_cmd_resp *cmd;
1186c349dbc7Sjsg 
11875ca02815Sjsg 	cmd = acquire_psp_cmd_buf(psp);
1188c349dbc7Sjsg 
11891bb76ff1Sjsg 	psp_copy_fw(psp, context->bin_desc.start_addr,
11901bb76ff1Sjsg 		    context->bin_desc.size_bytes);
1191c349dbc7Sjsg 
11921bb76ff1Sjsg 	psp_prep_ta_load_cmd_buf(cmd, psp->fw_pri_mc_addr, context);
1193c349dbc7Sjsg 
1194c349dbc7Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
1195c349dbc7Sjsg 				 psp->fence_buf_mc_addr);
1196c349dbc7Sjsg 
11971bb76ff1Sjsg 	context->resp_status = cmd->resp.status;
11981bb76ff1Sjsg 
1199f005ef32Sjsg 	if (!ret)
12001bb76ff1Sjsg 		context->session_id = cmd->resp.session_id;
1201c349dbc7Sjsg 
12025ca02815Sjsg 	release_psp_cmd_buf(psp);
1203c349dbc7Sjsg 
1204c349dbc7Sjsg 	return ret;
1205c349dbc7Sjsg }
1206c349dbc7Sjsg 
1207c349dbc7Sjsg int psp_xgmi_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
1208c349dbc7Sjsg {
12091bb76ff1Sjsg 	return psp_ta_invoke(psp, ta_cmd_id, &psp->xgmi_context.context);
1210c349dbc7Sjsg }
1211c349dbc7Sjsg 
1212c349dbc7Sjsg int psp_xgmi_terminate(struct psp_context *psp)
1213c349dbc7Sjsg {
1214c349dbc7Sjsg 	int ret;
12151bb76ff1Sjsg 	struct amdgpu_device *adev = psp->adev;
12161bb76ff1Sjsg 
12171bb76ff1Sjsg 	/* XGMI TA unload currently is not supported on Arcturus/Aldebaran A+A */
12181bb76ff1Sjsg 	if (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) ||
12191bb76ff1Sjsg 	    (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
12201bb76ff1Sjsg 	     adev->gmc.xgmi.connected_to_cpu))
12211bb76ff1Sjsg 		return 0;
1222c349dbc7Sjsg 
12235ca02815Sjsg 	if (!psp->xgmi_context.context.initialized)
1224c349dbc7Sjsg 		return 0;
1225c349dbc7Sjsg 
12261bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->xgmi_context.context);
1227c349dbc7Sjsg 
12285ca02815Sjsg 	psp->xgmi_context.context.initialized = false;
1229c349dbc7Sjsg 
12301bb76ff1Sjsg 	return ret;
1231c349dbc7Sjsg }
1232c349dbc7Sjsg 
12335ca02815Sjsg int psp_xgmi_initialize(struct psp_context *psp, bool set_extended_data, bool load_ta)
1234c349dbc7Sjsg {
1235c349dbc7Sjsg 	struct ta_xgmi_shared_memory *xgmi_cmd;
1236c349dbc7Sjsg 	int ret;
1237c349dbc7Sjsg 
12385ca02815Sjsg 	if (!psp->ta_fw ||
12391bb76ff1Sjsg 	    !psp->xgmi_context.context.bin_desc.size_bytes ||
12401bb76ff1Sjsg 	    !psp->xgmi_context.context.bin_desc.start_addr)
1241c349dbc7Sjsg 		return -ENOENT;
1242c349dbc7Sjsg 
12435ca02815Sjsg 	if (!load_ta)
12445ca02815Sjsg 		goto invoke;
12455ca02815Sjsg 
12461bb76ff1Sjsg 	psp->xgmi_context.context.mem_context.shared_mem_size = PSP_XGMI_SHARED_MEM_SIZE;
12471bb76ff1Sjsg 	psp->xgmi_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
12481bb76ff1Sjsg 
12491bb76ff1Sjsg 	if (!psp->xgmi_context.context.mem_context.shared_buf) {
12501bb76ff1Sjsg 		ret = psp_ta_init_shared_buf(psp, &psp->xgmi_context.context.mem_context);
1251c349dbc7Sjsg 		if (ret)
1252c349dbc7Sjsg 			return ret;
1253c349dbc7Sjsg 	}
1254c349dbc7Sjsg 
1255c349dbc7Sjsg 	/* Load XGMI TA */
12561bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->xgmi_context.context);
12571bb76ff1Sjsg 	if (!ret)
12581bb76ff1Sjsg 		psp->xgmi_context.context.initialized = true;
12591bb76ff1Sjsg 	else
1260c349dbc7Sjsg 		return ret;
1261c349dbc7Sjsg 
12625ca02815Sjsg invoke:
1263c349dbc7Sjsg 	/* Initialize XGMI session */
12645ca02815Sjsg 	xgmi_cmd = (struct ta_xgmi_shared_memory *)(psp->xgmi_context.context.mem_context.shared_buf);
1265c349dbc7Sjsg 	memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
12665ca02815Sjsg 	xgmi_cmd->flag_extend_link_record = set_extended_data;
1267c349dbc7Sjsg 	xgmi_cmd->cmd_id = TA_COMMAND_XGMI__INITIALIZE;
1268c349dbc7Sjsg 
1269c349dbc7Sjsg 	ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id);
1270c349dbc7Sjsg 
1271c349dbc7Sjsg 	return ret;
1272c349dbc7Sjsg }
1273c349dbc7Sjsg 
1274ad8b1aafSjsg int psp_xgmi_get_hive_id(struct psp_context *psp, uint64_t *hive_id)
1275ad8b1aafSjsg {
1276ad8b1aafSjsg 	struct ta_xgmi_shared_memory *xgmi_cmd;
1277ad8b1aafSjsg 	int ret;
1278ad8b1aafSjsg 
12795ca02815Sjsg 	xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
1280ad8b1aafSjsg 	memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
1281ad8b1aafSjsg 
1282ad8b1aafSjsg 	xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_HIVE_ID;
1283ad8b1aafSjsg 
1284ad8b1aafSjsg 	/* Invoke xgmi ta to get hive id */
1285ad8b1aafSjsg 	ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id);
1286ad8b1aafSjsg 	if (ret)
1287ad8b1aafSjsg 		return ret;
1288ad8b1aafSjsg 
1289ad8b1aafSjsg 	*hive_id = xgmi_cmd->xgmi_out_message.get_hive_id.hive_id;
1290ad8b1aafSjsg 
1291ad8b1aafSjsg 	return 0;
1292ad8b1aafSjsg }
1293ad8b1aafSjsg 
1294ad8b1aafSjsg int psp_xgmi_get_node_id(struct psp_context *psp, uint64_t *node_id)
1295ad8b1aafSjsg {
1296ad8b1aafSjsg 	struct ta_xgmi_shared_memory *xgmi_cmd;
1297ad8b1aafSjsg 	int ret;
1298ad8b1aafSjsg 
12995ca02815Sjsg 	xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
1300ad8b1aafSjsg 	memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
1301ad8b1aafSjsg 
1302ad8b1aafSjsg 	xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_NODE_ID;
1303ad8b1aafSjsg 
1304ad8b1aafSjsg 	/* Invoke xgmi ta to get the node id */
1305ad8b1aafSjsg 	ret = psp_xgmi_invoke(psp, xgmi_cmd->cmd_id);
1306ad8b1aafSjsg 	if (ret)
1307ad8b1aafSjsg 		return ret;
1308ad8b1aafSjsg 
1309ad8b1aafSjsg 	*node_id = xgmi_cmd->xgmi_out_message.get_node_id.node_id;
1310ad8b1aafSjsg 
1311ad8b1aafSjsg 	return 0;
1312ad8b1aafSjsg }
1313ad8b1aafSjsg 
13145ca02815Sjsg static bool psp_xgmi_peer_link_info_supported(struct psp_context *psp)
13155ca02815Sjsg {
1316f005ef32Sjsg 	return (psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 2) &&
1317f005ef32Sjsg 		psp->xgmi_context.context.bin_desc.fw_version >= 0x2000000b) ||
1318f005ef32Sjsg 		psp->adev->ip_versions[MP0_HWIP][0] >= IP_VERSION(13, 0, 6);
13195ca02815Sjsg }
13205ca02815Sjsg 
13215ca02815Sjsg /*
13225ca02815Sjsg  * Chips that support extended topology information require the driver to
13235ca02815Sjsg  * reflect topology information in the opposite direction.  This is
13245ca02815Sjsg  * because the TA has already exceeded its link record limit and if the
13255ca02815Sjsg  * TA holds bi-directional information, the driver would have to do
13265ca02815Sjsg  * multiple fetches instead of just two.
13275ca02815Sjsg  */
13285ca02815Sjsg static void psp_xgmi_reflect_topology_info(struct psp_context *psp,
13295ca02815Sjsg 					struct psp_xgmi_node_info node_info)
13305ca02815Sjsg {
13315ca02815Sjsg 	struct amdgpu_device *mirror_adev;
13325ca02815Sjsg 	struct amdgpu_hive_info *hive;
13335ca02815Sjsg 	uint64_t src_node_id = psp->adev->gmc.xgmi.node_id;
13345ca02815Sjsg 	uint64_t dst_node_id = node_info.node_id;
13355ca02815Sjsg 	uint8_t dst_num_hops = node_info.num_hops;
13365ca02815Sjsg 	uint8_t dst_num_links = node_info.num_links;
13375ca02815Sjsg 
13385ca02815Sjsg 	hive = amdgpu_get_xgmi_hive(psp->adev);
1339*99dcd02bSjsg 	if (WARN_ON(!hive))
1340*99dcd02bSjsg 		return;
1341*99dcd02bSjsg 
13425ca02815Sjsg 	list_for_each_entry(mirror_adev, &hive->device_list, gmc.xgmi.head) {
13435ca02815Sjsg 		struct psp_xgmi_topology_info *mirror_top_info;
13445ca02815Sjsg 		int j;
13455ca02815Sjsg 
13465ca02815Sjsg 		if (mirror_adev->gmc.xgmi.node_id != dst_node_id)
13475ca02815Sjsg 			continue;
13485ca02815Sjsg 
13495ca02815Sjsg 		mirror_top_info = &mirror_adev->psp.xgmi_context.top_info;
13505ca02815Sjsg 		for (j = 0; j < mirror_top_info->num_nodes; j++) {
13515ca02815Sjsg 			if (mirror_top_info->nodes[j].node_id != src_node_id)
13525ca02815Sjsg 				continue;
13535ca02815Sjsg 
13545ca02815Sjsg 			mirror_top_info->nodes[j].num_hops = dst_num_hops;
13555ca02815Sjsg 			/*
13565ca02815Sjsg 			 * prevent 0 num_links value re-reflection since reflection
13575ca02815Sjsg 			 * criteria is based on num_hops (direct or indirect).
13585ca02815Sjsg 			 *
13595ca02815Sjsg 			 */
13605ca02815Sjsg 			if (dst_num_links)
13615ca02815Sjsg 				mirror_top_info->nodes[j].num_links = dst_num_links;
13625ca02815Sjsg 
13635ca02815Sjsg 			break;
13645ca02815Sjsg 		}
13655ca02815Sjsg 
13665ca02815Sjsg 		break;
13675ca02815Sjsg 	}
13681bb76ff1Sjsg 
13691bb76ff1Sjsg 	amdgpu_put_xgmi_hive(hive);
13705ca02815Sjsg }
13715ca02815Sjsg 
1372ad8b1aafSjsg int psp_xgmi_get_topology_info(struct psp_context *psp,
1373ad8b1aafSjsg 			       int number_devices,
13745ca02815Sjsg 			       struct psp_xgmi_topology_info *topology,
13755ca02815Sjsg 			       bool get_extended_data)
1376ad8b1aafSjsg {
1377ad8b1aafSjsg 	struct ta_xgmi_shared_memory *xgmi_cmd;
1378ad8b1aafSjsg 	struct ta_xgmi_cmd_get_topology_info_input *topology_info_input;
1379ad8b1aafSjsg 	struct ta_xgmi_cmd_get_topology_info_output *topology_info_output;
1380ad8b1aafSjsg 	int i;
1381ad8b1aafSjsg 	int ret;
1382ad8b1aafSjsg 
1383ad8b1aafSjsg 	if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES)
1384ad8b1aafSjsg 		return -EINVAL;
1385ad8b1aafSjsg 
13865ca02815Sjsg 	xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
1387ad8b1aafSjsg 	memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
13885ca02815Sjsg 	xgmi_cmd->flag_extend_link_record = get_extended_data;
1389ad8b1aafSjsg 
1390ad8b1aafSjsg 	/* Fill in the shared memory with topology information as input */
1391ad8b1aafSjsg 	topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info;
1392ad8b1aafSjsg 	xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO;
1393ad8b1aafSjsg 	topology_info_input->num_nodes = number_devices;
1394ad8b1aafSjsg 
1395ad8b1aafSjsg 	for (i = 0; i < topology_info_input->num_nodes; i++) {
1396ad8b1aafSjsg 		topology_info_input->nodes[i].node_id = topology->nodes[i].node_id;
1397ad8b1aafSjsg 		topology_info_input->nodes[i].num_hops = topology->nodes[i].num_hops;
1398ad8b1aafSjsg 		topology_info_input->nodes[i].is_sharing_enabled = topology->nodes[i].is_sharing_enabled;
1399ad8b1aafSjsg 		topology_info_input->nodes[i].sdma_engine = topology->nodes[i].sdma_engine;
1400ad8b1aafSjsg 	}
1401ad8b1aafSjsg 
1402ad8b1aafSjsg 	/* Invoke xgmi ta to get the topology information */
1403ad8b1aafSjsg 	ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_GET_TOPOLOGY_INFO);
1404ad8b1aafSjsg 	if (ret)
1405ad8b1aafSjsg 		return ret;
1406ad8b1aafSjsg 
1407ad8b1aafSjsg 	/* Read the output topology information from the shared memory */
1408ad8b1aafSjsg 	topology_info_output = &xgmi_cmd->xgmi_out_message.get_topology_info;
1409ad8b1aafSjsg 	topology->num_nodes = xgmi_cmd->xgmi_out_message.get_topology_info.num_nodes;
1410ad8b1aafSjsg 	for (i = 0; i < topology->num_nodes; i++) {
14115ca02815Sjsg 		/* extended data will either be 0 or equal to non-extended data */
14125ca02815Sjsg 		if (topology_info_output->nodes[i].num_hops)
1413ad8b1aafSjsg 			topology->nodes[i].num_hops = topology_info_output->nodes[i].num_hops;
14145ca02815Sjsg 
14155ca02815Sjsg 		/* non-extended data gets everything here so no need to update */
14165ca02815Sjsg 		if (!get_extended_data) {
14175ca02815Sjsg 			topology->nodes[i].node_id = topology_info_output->nodes[i].node_id;
14185ca02815Sjsg 			topology->nodes[i].is_sharing_enabled =
14195ca02815Sjsg 					topology_info_output->nodes[i].is_sharing_enabled;
14205ca02815Sjsg 			topology->nodes[i].sdma_engine =
14215ca02815Sjsg 					topology_info_output->nodes[i].sdma_engine;
14225ca02815Sjsg 		}
14235ca02815Sjsg 
14245ca02815Sjsg 	}
14255ca02815Sjsg 
14265ca02815Sjsg 	/* Invoke xgmi ta again to get the link information */
14275ca02815Sjsg 	if (psp_xgmi_peer_link_info_supported(psp)) {
14285ca02815Sjsg 		struct ta_xgmi_cmd_get_peer_link_info_output *link_info_output;
1429f005ef32Sjsg 		bool requires_reflection =
1430f005ef32Sjsg 			(psp->xgmi_context.supports_extended_data && get_extended_data) ||
1431f005ef32Sjsg 				psp->adev->ip_versions[MP0_HWIP][0] == IP_VERSION(13, 0, 6);
14325ca02815Sjsg 
14335ca02815Sjsg 		xgmi_cmd->cmd_id = TA_COMMAND_XGMI__GET_PEER_LINKS;
14345ca02815Sjsg 
14355ca02815Sjsg 		ret = psp_xgmi_invoke(psp, TA_COMMAND_XGMI__GET_PEER_LINKS);
14365ca02815Sjsg 
14375ca02815Sjsg 		if (ret)
14385ca02815Sjsg 			return ret;
14395ca02815Sjsg 
14405ca02815Sjsg 		link_info_output = &xgmi_cmd->xgmi_out_message.get_link_info;
14415ca02815Sjsg 		for (i = 0; i < topology->num_nodes; i++) {
14425ca02815Sjsg 			/* accumulate num_links on extended data */
14435ca02815Sjsg 			topology->nodes[i].num_links = get_extended_data ?
14445ca02815Sjsg 					topology->nodes[i].num_links +
14455ca02815Sjsg 							link_info_output->nodes[i].num_links :
1446f005ef32Sjsg 					((requires_reflection && topology->nodes[i].num_links) ? topology->nodes[i].num_links :
1447f005ef32Sjsg 					 link_info_output->nodes[i].num_links);
14485ca02815Sjsg 
14495ca02815Sjsg 			/* reflect the topology information for bi-directionality */
1450f005ef32Sjsg 			if (requires_reflection && topology->nodes[i].num_hops)
14515ca02815Sjsg 				psp_xgmi_reflect_topology_info(psp, topology->nodes[i]);
14525ca02815Sjsg 		}
1453ad8b1aafSjsg 	}
1454ad8b1aafSjsg 
1455ad8b1aafSjsg 	return 0;
1456ad8b1aafSjsg }
1457ad8b1aafSjsg 
1458ad8b1aafSjsg int psp_xgmi_set_topology_info(struct psp_context *psp,
1459ad8b1aafSjsg 			       int number_devices,
1460ad8b1aafSjsg 			       struct psp_xgmi_topology_info *topology)
1461ad8b1aafSjsg {
1462ad8b1aafSjsg 	struct ta_xgmi_shared_memory *xgmi_cmd;
1463ad8b1aafSjsg 	struct ta_xgmi_cmd_get_topology_info_input *topology_info_input;
1464ad8b1aafSjsg 	int i;
1465ad8b1aafSjsg 
1466ad8b1aafSjsg 	if (!topology || topology->num_nodes > TA_XGMI__MAX_CONNECTED_NODES)
1467ad8b1aafSjsg 		return -EINVAL;
1468ad8b1aafSjsg 
14695ca02815Sjsg 	xgmi_cmd = (struct ta_xgmi_shared_memory *)psp->xgmi_context.context.mem_context.shared_buf;
1470ad8b1aafSjsg 	memset(xgmi_cmd, 0, sizeof(struct ta_xgmi_shared_memory));
1471ad8b1aafSjsg 
1472ad8b1aafSjsg 	topology_info_input = &xgmi_cmd->xgmi_in_message.get_topology_info;
1473ad8b1aafSjsg 	xgmi_cmd->cmd_id = TA_COMMAND_XGMI__SET_TOPOLOGY_INFO;
1474ad8b1aafSjsg 	topology_info_input->num_nodes = number_devices;
1475ad8b1aafSjsg 
1476ad8b1aafSjsg 	for (i = 0; i < topology_info_input->num_nodes; i++) {
1477ad8b1aafSjsg 		topology_info_input->nodes[i].node_id = topology->nodes[i].node_id;
1478ad8b1aafSjsg 		topology_info_input->nodes[i].num_hops = topology->nodes[i].num_hops;
1479ad8b1aafSjsg 		topology_info_input->nodes[i].is_sharing_enabled = 1;
1480ad8b1aafSjsg 		topology_info_input->nodes[i].sdma_engine = topology->nodes[i].sdma_engine;
1481ad8b1aafSjsg 	}
1482ad8b1aafSjsg 
1483ad8b1aafSjsg 	/* Invoke xgmi ta to set topology information */
1484ad8b1aafSjsg 	return psp_xgmi_invoke(psp, TA_COMMAND_XGMI__SET_TOPOLOGY_INFO);
1485ad8b1aafSjsg }
1486ad8b1aafSjsg 
1487c349dbc7Sjsg // ras begin
14881bb76ff1Sjsg static void psp_ras_ta_check_status(struct psp_context *psp)
1489c349dbc7Sjsg {
14901bb76ff1Sjsg 	struct ta_ras_shared_memory *ras_cmd =
14911bb76ff1Sjsg 		(struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
14921bb76ff1Sjsg 
14931bb76ff1Sjsg 	switch (ras_cmd->ras_status) {
14941bb76ff1Sjsg 	case TA_RAS_STATUS__ERROR_UNSUPPORTED_IP:
14951bb76ff1Sjsg 		dev_warn(psp->adev->dev,
14961bb76ff1Sjsg 				"RAS WARNING: cmd failed due to unsupported ip\n");
14971bb76ff1Sjsg 		break;
14981bb76ff1Sjsg 	case TA_RAS_STATUS__ERROR_UNSUPPORTED_ERROR_INJ:
14991bb76ff1Sjsg 		dev_warn(psp->adev->dev,
15001bb76ff1Sjsg 				"RAS WARNING: cmd failed due to unsupported error injection\n");
15011bb76ff1Sjsg 		break;
15021bb76ff1Sjsg 	case TA_RAS_STATUS__SUCCESS:
15031bb76ff1Sjsg 		break;
15041bb76ff1Sjsg 	case TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED:
15051bb76ff1Sjsg 		if (ras_cmd->cmd_id == TA_RAS_COMMAND__TRIGGER_ERROR)
15061bb76ff1Sjsg 			dev_warn(psp->adev->dev,
15071bb76ff1Sjsg 					"RAS WARNING: Inject error to critical region is not allowed\n");
15081bb76ff1Sjsg 		break;
15091bb76ff1Sjsg 	default:
15101bb76ff1Sjsg 		dev_warn(psp->adev->dev,
15111bb76ff1Sjsg 				"RAS WARNING: ras status = 0x%X\n", ras_cmd->ras_status);
15121bb76ff1Sjsg 		break;
1513c349dbc7Sjsg 	}
1514c349dbc7Sjsg }
1515c349dbc7Sjsg 
1516c349dbc7Sjsg int psp_ras_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
1517c349dbc7Sjsg {
1518ad8b1aafSjsg 	struct ta_ras_shared_memory *ras_cmd;
1519ad8b1aafSjsg 	int ret;
1520ad8b1aafSjsg 
15215ca02815Sjsg 	ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
1522ad8b1aafSjsg 
1523c349dbc7Sjsg 	/*
1524c349dbc7Sjsg 	 * TODO: bypass the loading in sriov for now
1525c349dbc7Sjsg 	 */
1526c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1527c349dbc7Sjsg 		return 0;
1528c349dbc7Sjsg 
15291bb76ff1Sjsg 	ret = psp_ta_invoke(psp, ta_cmd_id, &psp->ras_context.context);
1530ad8b1aafSjsg 
1531ad8b1aafSjsg 	if (amdgpu_ras_intr_triggered())
1532ad8b1aafSjsg 		return ret;
1533ad8b1aafSjsg 
1534f005ef32Sjsg 	if (ras_cmd->if_version > RAS_TA_HOST_IF_VER) {
1535ad8b1aafSjsg 		DRM_WARN("RAS: Unsupported Interface");
1536ad8b1aafSjsg 		return -EINVAL;
1537ad8b1aafSjsg 	}
1538ad8b1aafSjsg 
1539ad8b1aafSjsg 	if (!ret) {
1540ad8b1aafSjsg 		if (ras_cmd->ras_out_message.flags.err_inject_switch_disable_flag) {
1541ad8b1aafSjsg 			dev_warn(psp->adev->dev, "ECC switch disabled\n");
1542ad8b1aafSjsg 
1543ad8b1aafSjsg 			ras_cmd->ras_status = TA_RAS_STATUS__ERROR_RAS_NOT_AVAILABLE;
1544f005ef32Sjsg 		} else if (ras_cmd->ras_out_message.flags.reg_access_failure_flag)
1545ad8b1aafSjsg 			dev_warn(psp->adev->dev,
1546ad8b1aafSjsg 				 "RAS internal register access blocked\n");
1547ad8b1aafSjsg 
15481bb76ff1Sjsg 		psp_ras_ta_check_status(psp);
15495ca02815Sjsg 	}
15505ca02815Sjsg 
15515ca02815Sjsg 	return ret;
15525ca02815Sjsg }
15535ca02815Sjsg 
1554c349dbc7Sjsg int psp_ras_enable_features(struct psp_context *psp,
1555c349dbc7Sjsg 		union ta_ras_cmd_input *info, bool enable)
1556c349dbc7Sjsg {
1557c349dbc7Sjsg 	struct ta_ras_shared_memory *ras_cmd;
1558c349dbc7Sjsg 	int ret;
1559c349dbc7Sjsg 
15605ca02815Sjsg 	if (!psp->ras_context.context.initialized)
1561c349dbc7Sjsg 		return -EINVAL;
1562c349dbc7Sjsg 
15635ca02815Sjsg 	ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
1564c349dbc7Sjsg 	memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
1565c349dbc7Sjsg 
1566c349dbc7Sjsg 	if (enable)
1567c349dbc7Sjsg 		ras_cmd->cmd_id = TA_RAS_COMMAND__ENABLE_FEATURES;
1568c349dbc7Sjsg 	else
1569c349dbc7Sjsg 		ras_cmd->cmd_id = TA_RAS_COMMAND__DISABLE_FEATURES;
1570c349dbc7Sjsg 
1571c349dbc7Sjsg 	ras_cmd->ras_in_message = *info;
1572c349dbc7Sjsg 
1573c349dbc7Sjsg 	ret = psp_ras_invoke(psp, ras_cmd->cmd_id);
1574c349dbc7Sjsg 	if (ret)
1575c349dbc7Sjsg 		return -EINVAL;
1576c349dbc7Sjsg 
15771bb76ff1Sjsg 	return 0;
1578c349dbc7Sjsg }
1579c349dbc7Sjsg 
15801bb76ff1Sjsg int psp_ras_terminate(struct psp_context *psp)
1581c349dbc7Sjsg {
1582c349dbc7Sjsg 	int ret;
1583c349dbc7Sjsg 
1584c349dbc7Sjsg 	/*
1585c349dbc7Sjsg 	 * TODO: bypass the terminate in sriov for now
1586c349dbc7Sjsg 	 */
1587c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1588c349dbc7Sjsg 		return 0;
1589c349dbc7Sjsg 
15905ca02815Sjsg 	if (!psp->ras_context.context.initialized)
1591c349dbc7Sjsg 		return 0;
1592c349dbc7Sjsg 
15931bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->ras_context.context);
1594c349dbc7Sjsg 
15955ca02815Sjsg 	psp->ras_context.context.initialized = false;
1596c349dbc7Sjsg 
15971bb76ff1Sjsg 	return ret;
1598c349dbc7Sjsg }
1599c349dbc7Sjsg 
1600f005ef32Sjsg int psp_ras_initialize(struct psp_context *psp)
1601c349dbc7Sjsg {
1602c349dbc7Sjsg 	int ret;
16035ca02815Sjsg 	uint32_t boot_cfg = 0xFF;
16045ca02815Sjsg 	struct amdgpu_device *adev = psp->adev;
16051bb76ff1Sjsg 	struct ta_ras_shared_memory *ras_cmd;
1606c349dbc7Sjsg 
1607c349dbc7Sjsg 	/*
1608c349dbc7Sjsg 	 * TODO: bypass the initialize in sriov for now
1609c349dbc7Sjsg 	 */
16105ca02815Sjsg 	if (amdgpu_sriov_vf(adev))
1611c349dbc7Sjsg 		return 0;
1612c349dbc7Sjsg 
16131bb76ff1Sjsg 	if (!adev->psp.ras_context.context.bin_desc.size_bytes ||
16141bb76ff1Sjsg 	    !adev->psp.ras_context.context.bin_desc.start_addr) {
16155ca02815Sjsg 		dev_info(adev->dev, "RAS: optional ras ta ucode is not available\n");
1616c349dbc7Sjsg 		return 0;
1617c349dbc7Sjsg 	}
1618c349dbc7Sjsg 
16195ca02815Sjsg 	if (amdgpu_atomfirmware_dynamic_boot_config_supported(adev)) {
16205ca02815Sjsg 		/* query GECC enablement status from boot config
16215ca02815Sjsg 		 * boot_cfg: 1: GECC is enabled or 0: GECC is disabled
16225ca02815Sjsg 		 */
16235ca02815Sjsg 		ret = psp_boot_config_get(adev, &boot_cfg);
16245ca02815Sjsg 		if (ret)
16255ca02815Sjsg 			dev_warn(adev->dev, "PSP get boot config failed\n");
16265ca02815Sjsg 
16275ca02815Sjsg 		if (!amdgpu_ras_is_supported(psp->adev, AMDGPU_RAS_BLOCK__UMC)) {
16285ca02815Sjsg 			if (!boot_cfg) {
16295ca02815Sjsg 				dev_info(adev->dev, "GECC is disabled\n");
16305ca02815Sjsg 			} else {
16315ca02815Sjsg 				/* disable GECC in next boot cycle if ras is
16325ca02815Sjsg 				 * disabled by module parameter amdgpu_ras_enable
16335ca02815Sjsg 				 * and/or amdgpu_ras_mask, or boot_config_get call
16345ca02815Sjsg 				 * is failed
16355ca02815Sjsg 				 */
16365ca02815Sjsg 				ret = psp_boot_config_set(adev, 0);
16375ca02815Sjsg 				if (ret)
16385ca02815Sjsg 					dev_warn(adev->dev, "PSP set boot config failed\n");
16395ca02815Sjsg 				else
1640f005ef32Sjsg 					dev_warn(adev->dev, "GECC will be disabled in next boot cycle if set amdgpu_ras_enable and/or amdgpu_ras_mask to 0x0\n");
16415ca02815Sjsg 			}
16425ca02815Sjsg 		} else {
1643f005ef32Sjsg 			if (boot_cfg == 1) {
16445ca02815Sjsg 				dev_info(adev->dev, "GECC is enabled\n");
16455ca02815Sjsg 			} else {
16465ca02815Sjsg 				/* enable GECC in next boot cycle if it is disabled
16475ca02815Sjsg 				 * in boot config, or force enable GECC if failed to
16485ca02815Sjsg 				 * get boot configuration
16495ca02815Sjsg 				 */
16505ca02815Sjsg 				ret = psp_boot_config_set(adev, BOOT_CONFIG_GECC);
16515ca02815Sjsg 				if (ret)
16525ca02815Sjsg 					dev_warn(adev->dev, "PSP set boot config failed\n");
16535ca02815Sjsg 				else
16545ca02815Sjsg 					dev_warn(adev->dev, "GECC will be enabled in next boot cycle\n");
16555ca02815Sjsg 			}
16565ca02815Sjsg 		}
16575ca02815Sjsg 	}
16585ca02815Sjsg 
16591bb76ff1Sjsg 	psp->ras_context.context.mem_context.shared_mem_size = PSP_RAS_SHARED_MEM_SIZE;
16601bb76ff1Sjsg 	psp->ras_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
16611bb76ff1Sjsg 
1662f005ef32Sjsg 	if (!psp->ras_context.context.mem_context.shared_buf) {
16631bb76ff1Sjsg 		ret = psp_ta_init_shared_buf(psp, &psp->ras_context.context.mem_context);
1664c349dbc7Sjsg 		if (ret)
1665c349dbc7Sjsg 			return ret;
1666c349dbc7Sjsg 	}
1667c349dbc7Sjsg 
16681bb76ff1Sjsg 	ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
16691bb76ff1Sjsg 	memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
1670c349dbc7Sjsg 
16711bb76ff1Sjsg 	if (amdgpu_ras_is_poison_mode_supported(adev))
16721bb76ff1Sjsg 		ras_cmd->ras_in_message.init_flags.poison_mode_en = 1;
1673f005ef32Sjsg 	if (!adev->gmc.xgmi.connected_to_cpu && !adev->gmc.is_app_apu)
16741bb76ff1Sjsg 		ras_cmd->ras_in_message.init_flags.dgpu_mode = 1;
1675f005ef32Sjsg 	ras_cmd->ras_in_message.init_flags.xcc_mask =
1676f005ef32Sjsg 		adev->gfx.xcc_mask;
1677f005ef32Sjsg 	ras_cmd->ras_in_message.init_flags.channel_dis_num = hweight32(adev->gmc.m_half_use) * 2;
16781bb76ff1Sjsg 
16791bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->ras_context.context);
16801bb76ff1Sjsg 
16811bb76ff1Sjsg 	if (!ret && !ras_cmd->ras_status)
16821bb76ff1Sjsg 		psp->ras_context.context.initialized = true;
16831bb76ff1Sjsg 	else {
16841bb76ff1Sjsg 		if (ras_cmd->ras_status)
16851bb76ff1Sjsg 			dev_warn(psp->adev->dev, "RAS Init Status: 0x%X\n", ras_cmd->ras_status);
1686f005ef32Sjsg 
1687f005ef32Sjsg 		/* fail to load RAS TA */
1688f005ef32Sjsg 		psp->ras_context.context.initialized = false;
16891bb76ff1Sjsg 	}
16901bb76ff1Sjsg 
16911bb76ff1Sjsg 	return ret;
1692c349dbc7Sjsg }
1693ad8b1aafSjsg 
1694ad8b1aafSjsg int psp_ras_trigger_error(struct psp_context *psp,
1695f005ef32Sjsg 			  struct ta_ras_trigger_error_input *info, uint32_t instance_mask)
1696ad8b1aafSjsg {
1697ad8b1aafSjsg 	struct ta_ras_shared_memory *ras_cmd;
1698f005ef32Sjsg 	struct amdgpu_device *adev = psp->adev;
1699ad8b1aafSjsg 	int ret;
1700f005ef32Sjsg 	uint32_t dev_mask;
1701ad8b1aafSjsg 
17025ca02815Sjsg 	if (!psp->ras_context.context.initialized)
1703ad8b1aafSjsg 		return -EINVAL;
1704ad8b1aafSjsg 
1705f005ef32Sjsg 	switch (info->block_id) {
1706f005ef32Sjsg 	case TA_RAS_BLOCK__GFX:
1707f005ef32Sjsg 		dev_mask = GET_MASK(GC, instance_mask);
1708f005ef32Sjsg 		break;
1709f005ef32Sjsg 	case TA_RAS_BLOCK__SDMA:
1710f005ef32Sjsg 		dev_mask = GET_MASK(SDMA0, instance_mask);
1711f005ef32Sjsg 		break;
1712f005ef32Sjsg 	case TA_RAS_BLOCK__VCN:
1713f005ef32Sjsg 	case TA_RAS_BLOCK__JPEG:
1714f005ef32Sjsg 		dev_mask = GET_MASK(VCN, instance_mask);
1715f005ef32Sjsg 		break;
1716f005ef32Sjsg 	default:
1717f005ef32Sjsg 		dev_mask = instance_mask;
1718f005ef32Sjsg 		break;
1719f005ef32Sjsg 	}
1720f005ef32Sjsg 
1721f005ef32Sjsg 	/* reuse sub_block_index for backward compatibility */
1722f005ef32Sjsg 	dev_mask <<= AMDGPU_RAS_INST_SHIFT;
1723f005ef32Sjsg 	dev_mask &= AMDGPU_RAS_INST_MASK;
1724f005ef32Sjsg 	info->sub_block_index |= dev_mask;
1725f005ef32Sjsg 
17265ca02815Sjsg 	ras_cmd = (struct ta_ras_shared_memory *)psp->ras_context.context.mem_context.shared_buf;
1727ad8b1aafSjsg 	memset(ras_cmd, 0, sizeof(struct ta_ras_shared_memory));
1728ad8b1aafSjsg 
1729ad8b1aafSjsg 	ras_cmd->cmd_id = TA_RAS_COMMAND__TRIGGER_ERROR;
1730ad8b1aafSjsg 	ras_cmd->ras_in_message.trigger_error = *info;
1731ad8b1aafSjsg 
1732ad8b1aafSjsg 	ret = psp_ras_invoke(psp, ras_cmd->cmd_id);
1733ad8b1aafSjsg 	if (ret)
1734ad8b1aafSjsg 		return -EINVAL;
1735ad8b1aafSjsg 
1736ad8b1aafSjsg 	/* If err_event_athub occurs error inject was successful, however
1737f005ef32Sjsg 	 *  return status from TA is no long reliable
1738f005ef32Sjsg 	 */
1739ad8b1aafSjsg 	if (amdgpu_ras_intr_triggered())
1740ad8b1aafSjsg 		return 0;
1741ad8b1aafSjsg 
17421bb76ff1Sjsg 	if (ras_cmd->ras_status == TA_RAS_STATUS__TEE_ERROR_ACCESS_DENIED)
17431bb76ff1Sjsg 		return -EACCES;
17441bb76ff1Sjsg 	else if (ras_cmd->ras_status)
17451bb76ff1Sjsg 		return -EINVAL;
17461bb76ff1Sjsg 
17471bb76ff1Sjsg 	return 0;
1748ad8b1aafSjsg }
1749c349dbc7Sjsg // ras end
1750c349dbc7Sjsg 
1751c349dbc7Sjsg // HDCP start
1752c349dbc7Sjsg static int psp_hdcp_initialize(struct psp_context *psp)
1753c349dbc7Sjsg {
1754c349dbc7Sjsg 	int ret;
1755c349dbc7Sjsg 
1756c349dbc7Sjsg 	/*
1757c349dbc7Sjsg 	 * TODO: bypass the initialize in sriov for now
1758c349dbc7Sjsg 	 */
1759c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1760c349dbc7Sjsg 		return 0;
1761c349dbc7Sjsg 
17621bb76ff1Sjsg 	if (!psp->hdcp_context.context.bin_desc.size_bytes ||
17631bb76ff1Sjsg 	    !psp->hdcp_context.context.bin_desc.start_addr) {
1764c349dbc7Sjsg 		dev_info(psp->adev->dev, "HDCP: optional hdcp ta ucode is not available\n");
1765c349dbc7Sjsg 		return 0;
1766c349dbc7Sjsg 	}
1767c349dbc7Sjsg 
17681bb76ff1Sjsg 	psp->hdcp_context.context.mem_context.shared_mem_size = PSP_HDCP_SHARED_MEM_SIZE;
17691bb76ff1Sjsg 	psp->hdcp_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
17701bb76ff1Sjsg 
177155121f49Sjsg 	if (!psp->hdcp_context.context.mem_context.shared_buf) {
17721bb76ff1Sjsg 		ret = psp_ta_init_shared_buf(psp, &psp->hdcp_context.context.mem_context);
1773c349dbc7Sjsg 		if (ret)
1774c349dbc7Sjsg 			return ret;
1775c349dbc7Sjsg 	}
1776c349dbc7Sjsg 
17771bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->hdcp_context.context);
17781bb76ff1Sjsg 	if (!ret) {
17791bb76ff1Sjsg 		psp->hdcp_context.context.initialized = true;
17801bb76ff1Sjsg 		rw_init(&psp->hdcp_context.mutex, "pspcp");
1781c349dbc7Sjsg 	}
1782c349dbc7Sjsg 
1783c349dbc7Sjsg 	return ret;
1784c349dbc7Sjsg }
1785c349dbc7Sjsg 
1786c349dbc7Sjsg int psp_hdcp_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
1787c349dbc7Sjsg {
1788c349dbc7Sjsg 	/*
1789c349dbc7Sjsg 	 * TODO: bypass the loading in sriov for now
1790c349dbc7Sjsg 	 */
1791c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1792c349dbc7Sjsg 		return 0;
1793c349dbc7Sjsg 
17941bb76ff1Sjsg 	return psp_ta_invoke(psp, ta_cmd_id, &psp->hdcp_context.context);
1795c349dbc7Sjsg }
1796c349dbc7Sjsg 
1797c349dbc7Sjsg static int psp_hdcp_terminate(struct psp_context *psp)
1798c349dbc7Sjsg {
1799c349dbc7Sjsg 	int ret;
1800c349dbc7Sjsg 
1801c349dbc7Sjsg 	/*
1802c349dbc7Sjsg 	 * TODO: bypass the terminate in sriov for now
1803c349dbc7Sjsg 	 */
1804c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1805c349dbc7Sjsg 		return 0;
1806c349dbc7Sjsg 
18071bb76ff1Sjsg 	if (!psp->hdcp_context.context.initialized)
1808c349dbc7Sjsg 		return 0;
1809c349dbc7Sjsg 
18101bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->hdcp_context.context);
1811c349dbc7Sjsg 
18125ca02815Sjsg 	psp->hdcp_context.context.initialized = false;
1813c349dbc7Sjsg 
18141bb76ff1Sjsg 	return ret;
1815c349dbc7Sjsg }
1816c349dbc7Sjsg // HDCP end
1817c349dbc7Sjsg 
1818c349dbc7Sjsg // DTM start
1819c349dbc7Sjsg static int psp_dtm_initialize(struct psp_context *psp)
1820c349dbc7Sjsg {
1821c349dbc7Sjsg 	int ret;
1822c349dbc7Sjsg 
1823c349dbc7Sjsg 	/*
1824c349dbc7Sjsg 	 * TODO: bypass the initialize in sriov for now
1825c349dbc7Sjsg 	 */
1826c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1827c349dbc7Sjsg 		return 0;
1828c349dbc7Sjsg 
18291bb76ff1Sjsg 	if (!psp->dtm_context.context.bin_desc.size_bytes ||
18301bb76ff1Sjsg 	    !psp->dtm_context.context.bin_desc.start_addr) {
1831c349dbc7Sjsg 		dev_info(psp->adev->dev, "DTM: optional dtm ta ucode is not available\n");
1832c349dbc7Sjsg 		return 0;
1833c349dbc7Sjsg 	}
1834c349dbc7Sjsg 
18351bb76ff1Sjsg 	psp->dtm_context.context.mem_context.shared_mem_size = PSP_DTM_SHARED_MEM_SIZE;
18361bb76ff1Sjsg 	psp->dtm_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
18371bb76ff1Sjsg 
183855121f49Sjsg 	if (!psp->dtm_context.context.mem_context.shared_buf) {
18391bb76ff1Sjsg 		ret = psp_ta_init_shared_buf(psp, &psp->dtm_context.context.mem_context);
1840c349dbc7Sjsg 		if (ret)
1841c349dbc7Sjsg 			return ret;
1842c349dbc7Sjsg 	}
1843c349dbc7Sjsg 
18441bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->dtm_context.context);
18451bb76ff1Sjsg 	if (!ret) {
18461bb76ff1Sjsg 		psp->dtm_context.context.initialized = true;
18471bb76ff1Sjsg 		rw_init(&psp->dtm_context.mutex, "pspdtm");
1848c349dbc7Sjsg 	}
1849c349dbc7Sjsg 
1850c349dbc7Sjsg 	return ret;
1851c349dbc7Sjsg }
1852c349dbc7Sjsg 
1853c349dbc7Sjsg int psp_dtm_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
1854c349dbc7Sjsg {
1855c349dbc7Sjsg 	/*
1856c349dbc7Sjsg 	 * TODO: bypass the loading in sriov for now
1857c349dbc7Sjsg 	 */
1858c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1859c349dbc7Sjsg 		return 0;
1860c349dbc7Sjsg 
18611bb76ff1Sjsg 	return psp_ta_invoke(psp, ta_cmd_id, &psp->dtm_context.context);
1862c349dbc7Sjsg }
1863c349dbc7Sjsg 
1864c349dbc7Sjsg static int psp_dtm_terminate(struct psp_context *psp)
1865c349dbc7Sjsg {
1866c349dbc7Sjsg 	int ret;
1867c349dbc7Sjsg 
1868c349dbc7Sjsg 	/*
1869c349dbc7Sjsg 	 * TODO: bypass the terminate in sriov for now
1870c349dbc7Sjsg 	 */
1871c349dbc7Sjsg 	if (amdgpu_sriov_vf(psp->adev))
1872c349dbc7Sjsg 		return 0;
1873c349dbc7Sjsg 
18741bb76ff1Sjsg 	if (!psp->dtm_context.context.initialized)
1875c349dbc7Sjsg 		return 0;
1876c349dbc7Sjsg 
18771bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->dtm_context.context);
1878c349dbc7Sjsg 
18795ca02815Sjsg 	psp->dtm_context.context.initialized = false;
1880c349dbc7Sjsg 
18811bb76ff1Sjsg 	return ret;
1882c349dbc7Sjsg }
1883c349dbc7Sjsg // DTM end
1884c349dbc7Sjsg 
1885ad8b1aafSjsg // RAP start
1886ad8b1aafSjsg static int psp_rap_initialize(struct psp_context *psp)
1887ad8b1aafSjsg {
1888ad8b1aafSjsg 	int ret;
18895ca02815Sjsg 	enum ta_rap_status status = TA_RAP_STATUS__SUCCESS;
1890ad8b1aafSjsg 
1891ad8b1aafSjsg 	/*
1892ad8b1aafSjsg 	 * TODO: bypass the initialize in sriov for now
1893ad8b1aafSjsg 	 */
1894ad8b1aafSjsg 	if (amdgpu_sriov_vf(psp->adev))
1895ad8b1aafSjsg 		return 0;
1896ad8b1aafSjsg 
18971bb76ff1Sjsg 	if (!psp->rap_context.context.bin_desc.size_bytes ||
18981bb76ff1Sjsg 	    !psp->rap_context.context.bin_desc.start_addr) {
1899ad8b1aafSjsg 		dev_info(psp->adev->dev, "RAP: optional rap ta ucode is not available\n");
1900ad8b1aafSjsg 		return 0;
1901ad8b1aafSjsg 	}
1902ad8b1aafSjsg 
19031bb76ff1Sjsg 	psp->rap_context.context.mem_context.shared_mem_size = PSP_RAP_SHARED_MEM_SIZE;
19041bb76ff1Sjsg 	psp->rap_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
19051bb76ff1Sjsg 
190655121f49Sjsg 	if (!psp->rap_context.context.mem_context.shared_buf) {
19071bb76ff1Sjsg 		ret = psp_ta_init_shared_buf(psp, &psp->rap_context.context.mem_context);
1908ad8b1aafSjsg 		if (ret)
1909ad8b1aafSjsg 			return ret;
1910ad8b1aafSjsg 	}
1911ad8b1aafSjsg 
19121bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->rap_context.context);
19131bb76ff1Sjsg 	if (!ret) {
19141bb76ff1Sjsg 		psp->rap_context.context.initialized = true;
19151bb76ff1Sjsg 		rw_init(&psp->rap_context.mutex, "psprap");
19161bb76ff1Sjsg 	} else
1917ad8b1aafSjsg 		return ret;
1918ad8b1aafSjsg 
19195ca02815Sjsg 	ret = psp_rap_invoke(psp, TA_CMD_RAP__INITIALIZE, &status);
19205ca02815Sjsg 	if (ret || status != TA_RAP_STATUS__SUCCESS) {
19211bb76ff1Sjsg 		psp_rap_terminate(psp);
19221bb76ff1Sjsg 		/* free rap shared memory */
19235ca02815Sjsg 		psp_ta_free_shared_buf(&psp->rap_context.context.mem_context);
1924ad8b1aafSjsg 
19255ca02815Sjsg 		dev_warn(psp->adev->dev, "RAP TA initialize fail (%d) status %d.\n",
19265ca02815Sjsg 			 ret, status);
19275ca02815Sjsg 
19285ca02815Sjsg 		return ret;
1929ad8b1aafSjsg 	}
1930ad8b1aafSjsg 
1931ad8b1aafSjsg 	return 0;
1932ad8b1aafSjsg }
1933ad8b1aafSjsg 
1934ad8b1aafSjsg static int psp_rap_terminate(struct psp_context *psp)
1935ad8b1aafSjsg {
1936ad8b1aafSjsg 	int ret;
1937ad8b1aafSjsg 
19385ca02815Sjsg 	if (!psp->rap_context.context.initialized)
1939ad8b1aafSjsg 		return 0;
1940ad8b1aafSjsg 
19411bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->rap_context.context);
1942ad8b1aafSjsg 
19435ca02815Sjsg 	psp->rap_context.context.initialized = false;
1944ad8b1aafSjsg 
1945ad8b1aafSjsg 	return ret;
1946ad8b1aafSjsg }
1947ad8b1aafSjsg 
19485ca02815Sjsg int psp_rap_invoke(struct psp_context *psp, uint32_t ta_cmd_id, enum ta_rap_status *status)
1949ad8b1aafSjsg {
1950ad8b1aafSjsg 	struct ta_rap_shared_memory *rap_cmd;
19515ca02815Sjsg 	int ret = 0;
1952ad8b1aafSjsg 
19535ca02815Sjsg 	if (!psp->rap_context.context.initialized)
19545ca02815Sjsg 		return 0;
1955ad8b1aafSjsg 
1956ad8b1aafSjsg 	if (ta_cmd_id != TA_CMD_RAP__INITIALIZE &&
1957ad8b1aafSjsg 	    ta_cmd_id != TA_CMD_RAP__VALIDATE_L0)
1958ad8b1aafSjsg 		return -EINVAL;
1959ad8b1aafSjsg 
1960ad8b1aafSjsg 	mutex_lock(&psp->rap_context.mutex);
1961ad8b1aafSjsg 
1962ad8b1aafSjsg 	rap_cmd = (struct ta_rap_shared_memory *)
19635ca02815Sjsg 		  psp->rap_context.context.mem_context.shared_buf;
1964ad8b1aafSjsg 	memset(rap_cmd, 0, sizeof(struct ta_rap_shared_memory));
1965ad8b1aafSjsg 
1966ad8b1aafSjsg 	rap_cmd->cmd_id = ta_cmd_id;
1967ad8b1aafSjsg 	rap_cmd->validation_method_id = METHOD_A;
1968ad8b1aafSjsg 
19691bb76ff1Sjsg 	ret = psp_ta_invoke(psp, rap_cmd->cmd_id, &psp->rap_context.context);
19705ca02815Sjsg 	if (ret)
19715ca02815Sjsg 		goto out_unlock;
19725ca02815Sjsg 
19735ca02815Sjsg 	if (status)
19745ca02815Sjsg 		*status = rap_cmd->rap_status;
19755ca02815Sjsg 
19765ca02815Sjsg out_unlock:
1977ad8b1aafSjsg 	mutex_unlock(&psp->rap_context.mutex);
19785ca02815Sjsg 
19795ca02815Sjsg 	return ret;
19805ca02815Sjsg }
19815ca02815Sjsg // RAP end
19825ca02815Sjsg 
19835ca02815Sjsg /* securedisplay start */
19845ca02815Sjsg static int psp_securedisplay_initialize(struct psp_context *psp)
19855ca02815Sjsg {
19865ca02815Sjsg 	int ret;
1987f005ef32Sjsg 	struct ta_securedisplay_cmd *securedisplay_cmd;
19885ca02815Sjsg 
19895ca02815Sjsg 	/*
19905ca02815Sjsg 	 * TODO: bypass the initialize in sriov for now
19915ca02815Sjsg 	 */
19925ca02815Sjsg 	if (amdgpu_sriov_vf(psp->adev))
19935ca02815Sjsg 		return 0;
19945ca02815Sjsg 
19951bb76ff1Sjsg 	if (!psp->securedisplay_context.context.bin_desc.size_bytes ||
19961bb76ff1Sjsg 	    !psp->securedisplay_context.context.bin_desc.start_addr) {
19975ca02815Sjsg 		dev_info(psp->adev->dev, "SECUREDISPLAY: securedisplay ta ucode is not available\n");
19985ca02815Sjsg 		return 0;
19995ca02815Sjsg 	}
20005ca02815Sjsg 
20016d5481daSjsg #ifdef __OpenBSD__
20026d5481daSjsg 	/*
20036d5481daSjsg 	 * with 20230117 or later firmware or later on renoir:
20046d5481daSjsg 	 *
20056d5481daSjsg 	 * [drm] psp gfx command LOAD_TA(0x1) failed and response status is (0x7)
20066d5481daSjsg 	 * [drm] psp gfx command INVOKE_CMD(0x3) failed and response status is (0x4)
20076d5481daSjsg 	 * psp_securedisplay_parse_resp_status *ERROR* Secure display: Generic Failure
20086d5481daSjsg 	 * psp_securedisplay_initialize *ERROR* SECUREDISPLAY: query
20096d5481daSjsg 	 *   securedisplay TA failed. ret 0x0
20106d5481daSjsg 	 */
20116d5481daSjsg 	return 0;
20126d5481daSjsg #endif
20136d5481daSjsg 
20141bb76ff1Sjsg 	psp->securedisplay_context.context.mem_context.shared_mem_size =
20151bb76ff1Sjsg 		PSP_SECUREDISPLAY_SHARED_MEM_SIZE;
20161bb76ff1Sjsg 	psp->securedisplay_context.context.ta_load_type = GFX_CMD_ID_LOAD_TA;
20171bb76ff1Sjsg 
20185ca02815Sjsg 	if (!psp->securedisplay_context.context.initialized) {
20191bb76ff1Sjsg 		ret = psp_ta_init_shared_buf(psp,
20201bb76ff1Sjsg 					     &psp->securedisplay_context.context.mem_context);
20215ca02815Sjsg 		if (ret)
20225ca02815Sjsg 			return ret;
20235ca02815Sjsg 	}
20245ca02815Sjsg 
20251bb76ff1Sjsg 	ret = psp_ta_load(psp, &psp->securedisplay_context.context);
20261bb76ff1Sjsg 	if (!ret) {
20271bb76ff1Sjsg 		psp->securedisplay_context.context.initialized = true;
20281bb76ff1Sjsg 		rw_init(&psp->securedisplay_context.mutex, "pscm");
20291bb76ff1Sjsg 	} else
20305ca02815Sjsg 		return ret;
20315ca02815Sjsg 
2032f005ef32Sjsg 	mutex_lock(&psp->securedisplay_context.mutex);
2033f005ef32Sjsg 
20345ca02815Sjsg 	psp_prep_securedisplay_cmd_buf(psp, &securedisplay_cmd,
20355ca02815Sjsg 			TA_SECUREDISPLAY_COMMAND__QUERY_TA);
20365ca02815Sjsg 
20375ca02815Sjsg 	ret = psp_securedisplay_invoke(psp, TA_SECUREDISPLAY_COMMAND__QUERY_TA);
2038f005ef32Sjsg 
2039f005ef32Sjsg 	mutex_unlock(&psp->securedisplay_context.mutex);
2040f005ef32Sjsg 
20415ca02815Sjsg 	if (ret) {
20421bb76ff1Sjsg 		psp_securedisplay_terminate(psp);
20431bb76ff1Sjsg 		/* free securedisplay shared memory */
20445ca02815Sjsg 		psp_ta_free_shared_buf(&psp->securedisplay_context.context.mem_context);
20455ca02815Sjsg 		dev_err(psp->adev->dev, "SECUREDISPLAY TA initialize fail.\n");
20465ca02815Sjsg 		return -EINVAL;
20475ca02815Sjsg 	}
20485ca02815Sjsg 
20495ca02815Sjsg 	if (securedisplay_cmd->status != TA_SECUREDISPLAY_STATUS__SUCCESS) {
20505ca02815Sjsg 		psp_securedisplay_parse_resp_status(psp, securedisplay_cmd->status);
20515ca02815Sjsg 		dev_err(psp->adev->dev, "SECUREDISPLAY: query securedisplay TA failed. ret 0x%x\n",
20525ca02815Sjsg 			securedisplay_cmd->securedisplay_out_message.query_ta.query_cmd_ret);
20539ee584c9Sjsg 		/* don't try again */
20549ee584c9Sjsg 		psp->securedisplay_context.context.bin_desc.size_bytes = 0;
20555ca02815Sjsg 	}
20565ca02815Sjsg 
20575ca02815Sjsg 	return 0;
20585ca02815Sjsg }
20595ca02815Sjsg 
20605ca02815Sjsg static int psp_securedisplay_terminate(struct psp_context *psp)
20615ca02815Sjsg {
20625ca02815Sjsg 	int ret;
20635ca02815Sjsg 
20645ca02815Sjsg 	/*
20655ca02815Sjsg 	 * TODO:bypass the terminate in sriov for now
20665ca02815Sjsg 	 */
20675ca02815Sjsg 	if (amdgpu_sriov_vf(psp->adev))
20685ca02815Sjsg 		return 0;
20695ca02815Sjsg 
20705ca02815Sjsg 	if (!psp->securedisplay_context.context.initialized)
20715ca02815Sjsg 		return 0;
20725ca02815Sjsg 
20731bb76ff1Sjsg 	ret = psp_ta_unload(psp, &psp->securedisplay_context.context);
20745ca02815Sjsg 
20755ca02815Sjsg 	psp->securedisplay_context.context.initialized = false;
20765ca02815Sjsg 
20775ca02815Sjsg 	return ret;
20785ca02815Sjsg }
20795ca02815Sjsg 
20805ca02815Sjsg int psp_securedisplay_invoke(struct psp_context *psp, uint32_t ta_cmd_id)
20815ca02815Sjsg {
20825ca02815Sjsg 	int ret;
20835ca02815Sjsg 
20845ca02815Sjsg 	if (!psp->securedisplay_context.context.initialized)
20855ca02815Sjsg 		return -EINVAL;
20865ca02815Sjsg 
20875ca02815Sjsg 	if (ta_cmd_id != TA_SECUREDISPLAY_COMMAND__QUERY_TA &&
20885ca02815Sjsg 	    ta_cmd_id != TA_SECUREDISPLAY_COMMAND__SEND_ROI_CRC)
20895ca02815Sjsg 		return -EINVAL;
20905ca02815Sjsg 
20911bb76ff1Sjsg 	ret = psp_ta_invoke(psp, ta_cmd_id, &psp->securedisplay_context.context);
20925ca02815Sjsg 
20935ca02815Sjsg 	return ret;
20945ca02815Sjsg }
20955ca02815Sjsg /* SECUREDISPLAY end */
2096ad8b1aafSjsg 
2097f005ef32Sjsg int amdgpu_psp_wait_for_bootloader(struct amdgpu_device *adev)
2098f005ef32Sjsg {
2099f005ef32Sjsg 	struct psp_context *psp = &adev->psp;
2100f005ef32Sjsg 	int ret = 0;
2101f005ef32Sjsg 
2102f005ef32Sjsg 	if (!amdgpu_sriov_vf(adev) && psp->funcs && psp->funcs->wait_for_bootloader != NULL)
2103f005ef32Sjsg 		ret = psp->funcs->wait_for_bootloader(psp);
2104f005ef32Sjsg 
2105f005ef32Sjsg 	return ret;
2106f005ef32Sjsg }
2107f005ef32Sjsg 
2108fb4d8502Sjsg static int psp_hw_start(struct psp_context *psp)
2109fb4d8502Sjsg {
2110fb4d8502Sjsg 	struct amdgpu_device *adev = psp->adev;
2111fb4d8502Sjsg 	int ret;
2112fb4d8502Sjsg 
2113c349dbc7Sjsg 	if (!amdgpu_sriov_vf(adev)) {
21145ca02815Sjsg 		if ((is_psp_fw_valid(psp->kdb)) &&
2115c349dbc7Sjsg 		    (psp->funcs->bootloader_load_kdb != NULL)) {
2116c349dbc7Sjsg 			ret = psp_bootloader_load_kdb(psp);
2117c349dbc7Sjsg 			if (ret) {
2118c349dbc7Sjsg 				DRM_ERROR("PSP load kdb failed!\n");
2119fb4d8502Sjsg 				return ret;
2120c349dbc7Sjsg 			}
2121c349dbc7Sjsg 		}
2122fb4d8502Sjsg 
21235ca02815Sjsg 		if ((is_psp_fw_valid(psp->spl)) &&
21245ca02815Sjsg 		    (psp->funcs->bootloader_load_spl != NULL)) {
2125ad8b1aafSjsg 			ret = psp_bootloader_load_spl(psp);
2126ad8b1aafSjsg 			if (ret) {
2127ad8b1aafSjsg 				DRM_ERROR("PSP load spl failed!\n");
2128ad8b1aafSjsg 				return ret;
2129ad8b1aafSjsg 			}
2130ad8b1aafSjsg 		}
2131ad8b1aafSjsg 
21325ca02815Sjsg 		if ((is_psp_fw_valid(psp->sys)) &&
21335ca02815Sjsg 		    (psp->funcs->bootloader_load_sysdrv != NULL)) {
2134c349dbc7Sjsg 			ret = psp_bootloader_load_sysdrv(psp);
2135c349dbc7Sjsg 			if (ret) {
2136c349dbc7Sjsg 				DRM_ERROR("PSP load sys drv failed!\n");
2137fb4d8502Sjsg 				return ret;
2138fb4d8502Sjsg 			}
21395ca02815Sjsg 		}
2140fb4d8502Sjsg 
21415ca02815Sjsg 		if ((is_psp_fw_valid(psp->soc_drv)) &&
21425ca02815Sjsg 		    (psp->funcs->bootloader_load_soc_drv != NULL)) {
21435ca02815Sjsg 			ret = psp_bootloader_load_soc_drv(psp);
21445ca02815Sjsg 			if (ret) {
21455ca02815Sjsg 				DRM_ERROR("PSP load soc drv failed!\n");
21465ca02815Sjsg 				return ret;
21475ca02815Sjsg 			}
21485ca02815Sjsg 		}
21495ca02815Sjsg 
21505ca02815Sjsg 		if ((is_psp_fw_valid(psp->intf_drv)) &&
21515ca02815Sjsg 		    (psp->funcs->bootloader_load_intf_drv != NULL)) {
21525ca02815Sjsg 			ret = psp_bootloader_load_intf_drv(psp);
21535ca02815Sjsg 			if (ret) {
21545ca02815Sjsg 				DRM_ERROR("PSP load intf drv failed!\n");
21555ca02815Sjsg 				return ret;
21565ca02815Sjsg 			}
21575ca02815Sjsg 		}
21585ca02815Sjsg 
21595ca02815Sjsg 		if ((is_psp_fw_valid(psp->dbg_drv)) &&
21605ca02815Sjsg 		    (psp->funcs->bootloader_load_dbg_drv != NULL)) {
21615ca02815Sjsg 			ret = psp_bootloader_load_dbg_drv(psp);
21625ca02815Sjsg 			if (ret) {
21635ca02815Sjsg 				DRM_ERROR("PSP load dbg drv failed!\n");
21645ca02815Sjsg 				return ret;
21655ca02815Sjsg 			}
21665ca02815Sjsg 		}
21675ca02815Sjsg 
21681bb76ff1Sjsg 		if ((is_psp_fw_valid(psp->ras_drv)) &&
21691bb76ff1Sjsg 		    (psp->funcs->bootloader_load_ras_drv != NULL)) {
21701bb76ff1Sjsg 			ret = psp_bootloader_load_ras_drv(psp);
21711bb76ff1Sjsg 			if (ret) {
21721bb76ff1Sjsg 				DRM_ERROR("PSP load ras_drv failed!\n");
21731bb76ff1Sjsg 				return ret;
21741bb76ff1Sjsg 			}
21751bb76ff1Sjsg 		}
21761bb76ff1Sjsg 
21775ca02815Sjsg 		if ((is_psp_fw_valid(psp->sos)) &&
21785ca02815Sjsg 		    (psp->funcs->bootloader_load_sos != NULL)) {
2179c349dbc7Sjsg 			ret = psp_bootloader_load_sos(psp);
2180c349dbc7Sjsg 			if (ret) {
2181c349dbc7Sjsg 				DRM_ERROR("PSP load sos failed!\n");
2182c349dbc7Sjsg 				return ret;
2183c349dbc7Sjsg 			}
2184c349dbc7Sjsg 		}
21855ca02815Sjsg 	}
2186c349dbc7Sjsg 
2187fb4d8502Sjsg 	ret = psp_ring_create(psp, PSP_RING_TYPE__KM);
2188c349dbc7Sjsg 	if (ret) {
2189c349dbc7Sjsg 		DRM_ERROR("PSP create ring failed!\n");
2190fb4d8502Sjsg 		return ret;
2191c349dbc7Sjsg 	}
2192fb4d8502Sjsg 
21937ec34d6bSjsg 	if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev))
21947ec34d6bSjsg 		goto skip_pin_bo;
21957ec34d6bSjsg 
2196f005ef32Sjsg 	if (!psp_boottime_tmr(psp)) {
2197c349dbc7Sjsg 		ret = psp_tmr_init(psp);
2198c349dbc7Sjsg 		if (ret) {
2199c349dbc7Sjsg 			DRM_ERROR("PSP tmr init failed!\n");
2200c349dbc7Sjsg 			return ret;
2201c349dbc7Sjsg 		}
2202f005ef32Sjsg 	}
2203c349dbc7Sjsg 
22047ec34d6bSjsg skip_pin_bo:
2205c349dbc7Sjsg 	/*
2206ad8b1aafSjsg 	 * For ASICs with DF Cstate management centralized
2207c349dbc7Sjsg 	 * to PMFW, TMR setup should be performed after PMFW
2208c349dbc7Sjsg 	 * loaded and before other non-psp firmware loaded.
2209c349dbc7Sjsg 	 */
2210ad8b1aafSjsg 	if (psp->pmfw_centralized_cstate_management) {
2211ad8b1aafSjsg 		ret = psp_load_smu_fw(psp);
2212ad8b1aafSjsg 		if (ret)
2213ad8b1aafSjsg 			return ret;
2214ad8b1aafSjsg 	}
2215ad8b1aafSjsg 
2216fb4d8502Sjsg 	ret = psp_tmr_load(psp);
2217c349dbc7Sjsg 	if (ret) {
2218c349dbc7Sjsg 		DRM_ERROR("PSP load tmr failed!\n");
2219fb4d8502Sjsg 		return ret;
2220c349dbc7Sjsg 	}
2221fb4d8502Sjsg 
2222fb4d8502Sjsg 	return 0;
2223fb4d8502Sjsg }
2224fb4d8502Sjsg 
2225c349dbc7Sjsg static int psp_get_fw_type(struct amdgpu_firmware_info *ucode,
2226c349dbc7Sjsg 			   enum psp_gfx_fw_type *type)
2227c349dbc7Sjsg {
2228c349dbc7Sjsg 	switch (ucode->ucode_id) {
22291bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CAP:
22301bb76ff1Sjsg 		*type = GFX_FW_TYPE_CAP;
22311bb76ff1Sjsg 		break;
2232c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA0:
2233c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA0;
2234c349dbc7Sjsg 		break;
2235c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA1:
2236c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA1;
2237c349dbc7Sjsg 		break;
2238c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA2:
2239c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA2;
2240c349dbc7Sjsg 		break;
2241c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA3:
2242c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA3;
2243c349dbc7Sjsg 		break;
2244c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA4:
2245c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA4;
2246c349dbc7Sjsg 		break;
2247c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA5:
2248c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA5;
2249c349dbc7Sjsg 		break;
2250c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA6:
2251c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA6;
2252c349dbc7Sjsg 		break;
2253c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA7:
2254c349dbc7Sjsg 		*type = GFX_FW_TYPE_SDMA7;
2255c349dbc7Sjsg 		break;
2256ad8b1aafSjsg 	case AMDGPU_UCODE_ID_CP_MES:
2257ad8b1aafSjsg 		*type = GFX_FW_TYPE_CP_MES;
2258ad8b1aafSjsg 		break;
2259ad8b1aafSjsg 	case AMDGPU_UCODE_ID_CP_MES_DATA:
2260ad8b1aafSjsg 		*type = GFX_FW_TYPE_MES_STACK;
2261ad8b1aafSjsg 		break;
22621bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_MES1:
22631bb76ff1Sjsg 		*type = GFX_FW_TYPE_CP_MES_KIQ;
22641bb76ff1Sjsg 		break;
22651bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_MES1_DATA:
22661bb76ff1Sjsg 		*type = GFX_FW_TYPE_MES_KIQ_STACK;
22671bb76ff1Sjsg 		break;
2268c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_CE:
2269c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_CE;
2270c349dbc7Sjsg 		break;
2271c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_PFP:
2272c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_PFP;
2273c349dbc7Sjsg 		break;
2274c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_ME:
2275c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_ME;
2276c349dbc7Sjsg 		break;
2277c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_MEC1:
2278c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_MEC;
2279c349dbc7Sjsg 		break;
2280c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_MEC1_JT:
2281c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_MEC_ME1;
2282c349dbc7Sjsg 		break;
2283c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_MEC2:
2284c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_MEC;
2285c349dbc7Sjsg 		break;
2286c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_MEC2_JT:
2287c349dbc7Sjsg 		*type = GFX_FW_TYPE_CP_MEC_ME2;
2288c349dbc7Sjsg 		break;
22891bb76ff1Sjsg 	case AMDGPU_UCODE_ID_RLC_P:
22901bb76ff1Sjsg 		*type = GFX_FW_TYPE_RLC_P;
22911bb76ff1Sjsg 		break;
22921bb76ff1Sjsg 	case AMDGPU_UCODE_ID_RLC_V:
22931bb76ff1Sjsg 		*type = GFX_FW_TYPE_RLC_V;
22941bb76ff1Sjsg 		break;
2295c349dbc7Sjsg 	case AMDGPU_UCODE_ID_RLC_G:
2296c349dbc7Sjsg 		*type = GFX_FW_TYPE_RLC_G;
2297c349dbc7Sjsg 		break;
2298c349dbc7Sjsg 	case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_CNTL:
2299c349dbc7Sjsg 		*type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_CNTL;
2300c349dbc7Sjsg 		break;
2301c349dbc7Sjsg 	case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_GPM_MEM:
2302c349dbc7Sjsg 		*type = GFX_FW_TYPE_RLC_RESTORE_LIST_GPM_MEM;
2303c349dbc7Sjsg 		break;
2304c349dbc7Sjsg 	case AMDGPU_UCODE_ID_RLC_RESTORE_LIST_SRM_MEM:
2305c349dbc7Sjsg 		*type = GFX_FW_TYPE_RLC_RESTORE_LIST_SRM_MEM;
2306c349dbc7Sjsg 		break;
2307ad8b1aafSjsg 	case AMDGPU_UCODE_ID_RLC_IRAM:
2308ad8b1aafSjsg 		*type = GFX_FW_TYPE_RLC_IRAM;
2309ad8b1aafSjsg 		break;
2310ad8b1aafSjsg 	case AMDGPU_UCODE_ID_RLC_DRAM:
2311ad8b1aafSjsg 		*type = GFX_FW_TYPE_RLC_DRAM_BOOT;
2312ad8b1aafSjsg 		break;
23131bb76ff1Sjsg 	case AMDGPU_UCODE_ID_GLOBAL_TAP_DELAYS:
23141bb76ff1Sjsg 		*type = GFX_FW_TYPE_GLOBAL_TAP_DELAYS;
23151bb76ff1Sjsg 		break;
23161bb76ff1Sjsg 	case AMDGPU_UCODE_ID_SE0_TAP_DELAYS:
23171bb76ff1Sjsg 		*type = GFX_FW_TYPE_SE0_TAP_DELAYS;
23181bb76ff1Sjsg 		break;
23191bb76ff1Sjsg 	case AMDGPU_UCODE_ID_SE1_TAP_DELAYS:
23201bb76ff1Sjsg 		*type = GFX_FW_TYPE_SE1_TAP_DELAYS;
23211bb76ff1Sjsg 		break;
23221bb76ff1Sjsg 	case AMDGPU_UCODE_ID_SE2_TAP_DELAYS:
23231bb76ff1Sjsg 		*type = GFX_FW_TYPE_SE2_TAP_DELAYS;
23241bb76ff1Sjsg 		break;
23251bb76ff1Sjsg 	case AMDGPU_UCODE_ID_SE3_TAP_DELAYS:
23261bb76ff1Sjsg 		*type = GFX_FW_TYPE_SE3_TAP_DELAYS;
23271bb76ff1Sjsg 		break;
2328c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SMC:
2329c349dbc7Sjsg 		*type = GFX_FW_TYPE_SMU;
2330c349dbc7Sjsg 		break;
23311bb76ff1Sjsg 	case AMDGPU_UCODE_ID_PPTABLE:
23321bb76ff1Sjsg 		*type = GFX_FW_TYPE_PPTABLE;
23331bb76ff1Sjsg 		break;
2334c349dbc7Sjsg 	case AMDGPU_UCODE_ID_UVD:
2335c349dbc7Sjsg 		*type = GFX_FW_TYPE_UVD;
2336c349dbc7Sjsg 		break;
2337c349dbc7Sjsg 	case AMDGPU_UCODE_ID_UVD1:
2338c349dbc7Sjsg 		*type = GFX_FW_TYPE_UVD1;
2339c349dbc7Sjsg 		break;
2340c349dbc7Sjsg 	case AMDGPU_UCODE_ID_VCE:
2341c349dbc7Sjsg 		*type = GFX_FW_TYPE_VCE;
2342c349dbc7Sjsg 		break;
2343c349dbc7Sjsg 	case AMDGPU_UCODE_ID_VCN:
2344c349dbc7Sjsg 		*type = GFX_FW_TYPE_VCN;
2345c349dbc7Sjsg 		break;
2346c349dbc7Sjsg 	case AMDGPU_UCODE_ID_VCN1:
2347c349dbc7Sjsg 		*type = GFX_FW_TYPE_VCN1;
2348c349dbc7Sjsg 		break;
2349c349dbc7Sjsg 	case AMDGPU_UCODE_ID_DMCU_ERAM:
2350c349dbc7Sjsg 		*type = GFX_FW_TYPE_DMCU_ERAM;
2351c349dbc7Sjsg 		break;
2352c349dbc7Sjsg 	case AMDGPU_UCODE_ID_DMCU_INTV:
2353c349dbc7Sjsg 		*type = GFX_FW_TYPE_DMCU_ISR;
2354c349dbc7Sjsg 		break;
2355c349dbc7Sjsg 	case AMDGPU_UCODE_ID_VCN0_RAM:
2356c349dbc7Sjsg 		*type = GFX_FW_TYPE_VCN0_RAM;
2357c349dbc7Sjsg 		break;
2358c349dbc7Sjsg 	case AMDGPU_UCODE_ID_VCN1_RAM:
2359c349dbc7Sjsg 		*type = GFX_FW_TYPE_VCN1_RAM;
2360c349dbc7Sjsg 		break;
2361c349dbc7Sjsg 	case AMDGPU_UCODE_ID_DMCUB:
2362c349dbc7Sjsg 		*type = GFX_FW_TYPE_DMUB;
2363c349dbc7Sjsg 		break;
23641bb76ff1Sjsg 	case AMDGPU_UCODE_ID_SDMA_UCODE_TH0:
23651bb76ff1Sjsg 		*type = GFX_FW_TYPE_SDMA_UCODE_TH0;
23661bb76ff1Sjsg 		break;
23671bb76ff1Sjsg 	case AMDGPU_UCODE_ID_SDMA_UCODE_TH1:
23681bb76ff1Sjsg 		*type = GFX_FW_TYPE_SDMA_UCODE_TH1;
23691bb76ff1Sjsg 		break;
23701bb76ff1Sjsg 	case AMDGPU_UCODE_ID_IMU_I:
23711bb76ff1Sjsg 		*type = GFX_FW_TYPE_IMU_I;
23721bb76ff1Sjsg 		break;
23731bb76ff1Sjsg 	case AMDGPU_UCODE_ID_IMU_D:
23741bb76ff1Sjsg 		*type = GFX_FW_TYPE_IMU_D;
23751bb76ff1Sjsg 		break;
23761bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_PFP:
23771bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_PFP;
23781bb76ff1Sjsg 		break;
23791bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_ME:
23801bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_ME;
23811bb76ff1Sjsg 		break;
23821bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_MEC:
23831bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_MEC;
23841bb76ff1Sjsg 		break;
23851bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_PFP_P0_STACK:
23861bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_PFP_P0_STACK;
23871bb76ff1Sjsg 		break;
23881bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_PFP_P1_STACK:
23891bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_PFP_P1_STACK;
23901bb76ff1Sjsg 		break;
23911bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_ME_P0_STACK:
23921bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_ME_P0_STACK;
23931bb76ff1Sjsg 		break;
23941bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_ME_P1_STACK:
23951bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_ME_P1_STACK;
23961bb76ff1Sjsg 		break;
23971bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_MEC_P0_STACK:
23981bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_MEC_P0_STACK;
23991bb76ff1Sjsg 		break;
24001bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_MEC_P1_STACK:
24011bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_MEC_P1_STACK;
24021bb76ff1Sjsg 		break;
24031bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_MEC_P2_STACK:
24041bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_MEC_P2_STACK;
24051bb76ff1Sjsg 		break;
24061bb76ff1Sjsg 	case AMDGPU_UCODE_ID_CP_RS64_MEC_P3_STACK:
24071bb76ff1Sjsg 		*type = GFX_FW_TYPE_RS64_MEC_P3_STACK;
24081bb76ff1Sjsg 		break;
2409c349dbc7Sjsg 	case AMDGPU_UCODE_ID_MAXIMUM:
2410c349dbc7Sjsg 	default:
2411c349dbc7Sjsg 		return -EINVAL;
2412c349dbc7Sjsg 	}
2413c349dbc7Sjsg 
2414c349dbc7Sjsg 	return 0;
2415c349dbc7Sjsg }
2416c349dbc7Sjsg 
2417c349dbc7Sjsg static void psp_print_fw_hdr(struct psp_context *psp,
2418c349dbc7Sjsg 			     struct amdgpu_firmware_info *ucode)
2419c349dbc7Sjsg {
2420c349dbc7Sjsg 	struct amdgpu_device *adev = psp->adev;
2421c349dbc7Sjsg 	struct common_firmware_header *hdr;
2422c349dbc7Sjsg 
2423c349dbc7Sjsg 	switch (ucode->ucode_id) {
2424c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA0:
2425c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA1:
2426c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA2:
2427c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA3:
2428c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA4:
2429c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA5:
2430c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA6:
2431c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SDMA7:
2432c349dbc7Sjsg 		hdr = (struct common_firmware_header *)
2433c349dbc7Sjsg 			adev->sdma.instance[ucode->ucode_id - AMDGPU_UCODE_ID_SDMA0].fw->data;
2434c349dbc7Sjsg 		amdgpu_ucode_print_sdma_hdr(hdr);
2435c349dbc7Sjsg 		break;
2436c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_CE:
2437c349dbc7Sjsg 		hdr = (struct common_firmware_header *)adev->gfx.ce_fw->data;
2438c349dbc7Sjsg 		amdgpu_ucode_print_gfx_hdr(hdr);
2439c349dbc7Sjsg 		break;
2440c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_PFP:
2441c349dbc7Sjsg 		hdr = (struct common_firmware_header *)adev->gfx.pfp_fw->data;
2442c349dbc7Sjsg 		amdgpu_ucode_print_gfx_hdr(hdr);
2443c349dbc7Sjsg 		break;
2444c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_ME:
2445c349dbc7Sjsg 		hdr = (struct common_firmware_header *)adev->gfx.me_fw->data;
2446c349dbc7Sjsg 		amdgpu_ucode_print_gfx_hdr(hdr);
2447c349dbc7Sjsg 		break;
2448c349dbc7Sjsg 	case AMDGPU_UCODE_ID_CP_MEC1:
2449c349dbc7Sjsg 		hdr = (struct common_firmware_header *)adev->gfx.mec_fw->data;
2450c349dbc7Sjsg 		amdgpu_ucode_print_gfx_hdr(hdr);
2451c349dbc7Sjsg 		break;
2452c349dbc7Sjsg 	case AMDGPU_UCODE_ID_RLC_G:
2453c349dbc7Sjsg 		hdr = (struct common_firmware_header *)adev->gfx.rlc_fw->data;
2454c349dbc7Sjsg 		amdgpu_ucode_print_rlc_hdr(hdr);
2455c349dbc7Sjsg 		break;
2456c349dbc7Sjsg 	case AMDGPU_UCODE_ID_SMC:
2457c349dbc7Sjsg 		hdr = (struct common_firmware_header *)adev->pm.fw->data;
2458c349dbc7Sjsg 		amdgpu_ucode_print_smc_hdr(hdr);
2459c349dbc7Sjsg 		break;
2460c349dbc7Sjsg 	default:
2461c349dbc7Sjsg 		break;
2462c349dbc7Sjsg 	}
2463c349dbc7Sjsg }
2464c349dbc7Sjsg 
2465c349dbc7Sjsg static int psp_prep_load_ip_fw_cmd_buf(struct amdgpu_firmware_info *ucode,
2466c349dbc7Sjsg 				       struct psp_gfx_cmd_resp *cmd)
2467c349dbc7Sjsg {
2468c349dbc7Sjsg 	int ret;
2469c349dbc7Sjsg 	uint64_t fw_mem_mc_addr = ucode->mc_addr;
2470c349dbc7Sjsg 
2471c349dbc7Sjsg 	cmd->cmd_id = GFX_CMD_ID_LOAD_IP_FW;
2472c349dbc7Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_phy_addr_lo = lower_32_bits(fw_mem_mc_addr);
2473c349dbc7Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_phy_addr_hi = upper_32_bits(fw_mem_mc_addr);
2474c349dbc7Sjsg 	cmd->cmd.cmd_load_ip_fw.fw_size = ucode->ucode_size;
2475c349dbc7Sjsg 
2476c349dbc7Sjsg 	ret = psp_get_fw_type(ucode, &cmd->cmd.cmd_load_ip_fw.fw_type);
2477c349dbc7Sjsg 	if (ret)
2478c349dbc7Sjsg 		DRM_ERROR("Unknown firmware type\n");
2479c349dbc7Sjsg 
2480c349dbc7Sjsg 	return ret;
2481c349dbc7Sjsg }
2482c349dbc7Sjsg 
2483f005ef32Sjsg int psp_execute_ip_fw_load(struct psp_context *psp,
2484c349dbc7Sjsg 			   struct amdgpu_firmware_info *ucode)
2485c349dbc7Sjsg {
2486c349dbc7Sjsg 	int ret = 0;
24875ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
2488c349dbc7Sjsg 
24895ca02815Sjsg 	ret = psp_prep_load_ip_fw_cmd_buf(ucode, cmd);
24905ca02815Sjsg 	if (!ret) {
24915ca02815Sjsg 		ret = psp_cmd_submit_buf(psp, ucode, cmd,
2492c349dbc7Sjsg 					 psp->fence_buf_mc_addr);
24935ca02815Sjsg 	}
24945ca02815Sjsg 
24955ca02815Sjsg 	release_psp_cmd_buf(psp);
2496c349dbc7Sjsg 
2497c349dbc7Sjsg 	return ret;
2498c349dbc7Sjsg }
2499c349dbc7Sjsg 
2500ad8b1aafSjsg static int psp_load_smu_fw(struct psp_context *psp)
2501fb4d8502Sjsg {
2502ad8b1aafSjsg 	int ret;
2503fb4d8502Sjsg 	struct amdgpu_device *adev = psp->adev;
2504ad8b1aafSjsg 	struct amdgpu_firmware_info *ucode =
2505ad8b1aafSjsg 			&adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
25065ca02815Sjsg 	struct amdgpu_ras *ras = psp->ras_context.ras;
2507fb4d8502Sjsg 
25081bb76ff1Sjsg 	/*
25091bb76ff1Sjsg 	 * Skip SMU FW reloading in case of using BACO for runpm only,
25101bb76ff1Sjsg 	 * as SMU is always alive.
25111bb76ff1Sjsg 	 */
25121bb76ff1Sjsg 	if (adev->in_runpm && (adev->pm.rpm_mode == AMDGPU_RUNPM_BACO))
25131bb76ff1Sjsg 		return 0;
25141bb76ff1Sjsg 
2515ad8b1aafSjsg 	if (!ucode->fw || amdgpu_sriov_vf(psp->adev))
2516ad8b1aafSjsg 		return 0;
2517ad8b1aafSjsg 
25185ca02815Sjsg 	if ((amdgpu_in_reset(adev) &&
25195ca02815Sjsg 	     ras && adev->ras_enabled &&
25201bb76ff1Sjsg 	     (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 4) ||
25211bb76ff1Sjsg 	      adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 2)))) {
2522ad8b1aafSjsg 		ret = amdgpu_dpm_set_mp1_state(adev, PP_MP1_STATE_UNLOAD);
2523f005ef32Sjsg 		if (ret)
2524ad8b1aafSjsg 			DRM_WARN("Failed to set MP1 state prepare for reload\n");
2525ad8b1aafSjsg 	}
2526c349dbc7Sjsg 
2527f005ef32Sjsg 	ret = psp_execute_ip_fw_load(psp, ucode);
2528ad8b1aafSjsg 
2529c349dbc7Sjsg 	if (ret)
2530ad8b1aafSjsg 		DRM_ERROR("PSP load smu failed!\n");
2531ad8b1aafSjsg 
2532c349dbc7Sjsg 	return ret;
2533c349dbc7Sjsg }
2534c349dbc7Sjsg 
2535ad8b1aafSjsg static bool fw_load_skip_check(struct psp_context *psp,
2536ad8b1aafSjsg 			       struct amdgpu_firmware_info *ucode)
2537ad8b1aafSjsg {
2538eb9d8ed0Sjsg 	if (!ucode->fw || !ucode->ucode_size)
2539ad8b1aafSjsg 		return true;
2540fb4d8502Sjsg 
2541fb4d8502Sjsg 	if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
2542c349dbc7Sjsg 	    (psp_smu_reload_quirk(psp) ||
2543c349dbc7Sjsg 	     psp->autoload_supported ||
2544c349dbc7Sjsg 	     psp->pmfw_centralized_cstate_management))
2545ad8b1aafSjsg 		return true;
2546c349dbc7Sjsg 
2547ad8b1aafSjsg 	if (amdgpu_sriov_vf(psp->adev) &&
25481bb76ff1Sjsg 	    amdgpu_virt_fw_load_skip_check(psp->adev, ucode->ucode_id))
2549ad8b1aafSjsg 		return true;
2550fb4d8502Sjsg 
2551c349dbc7Sjsg 	if (psp->autoload_supported &&
2552c349dbc7Sjsg 	    (ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC1_JT ||
2553c349dbc7Sjsg 	     ucode->ucode_id == AMDGPU_UCODE_ID_CP_MEC2_JT))
2554c349dbc7Sjsg 		/* skip mec JT when autoload is enabled */
2555ad8b1aafSjsg 		return true;
2556ad8b1aafSjsg 
2557ad8b1aafSjsg 	return false;
2558ad8b1aafSjsg }
2559ad8b1aafSjsg 
25605ca02815Sjsg int psp_load_fw_list(struct psp_context *psp,
25615ca02815Sjsg 		     struct amdgpu_firmware_info **ucode_list, int ucode_count)
25625ca02815Sjsg {
25635ca02815Sjsg 	int ret = 0, i;
25645ca02815Sjsg 	struct amdgpu_firmware_info *ucode;
25655ca02815Sjsg 
25665ca02815Sjsg 	for (i = 0; i < ucode_count; ++i) {
25675ca02815Sjsg 		ucode = ucode_list[i];
25685ca02815Sjsg 		psp_print_fw_hdr(psp, ucode);
2569f005ef32Sjsg 		ret = psp_execute_ip_fw_load(psp, ucode);
25705ca02815Sjsg 		if (ret)
25715ca02815Sjsg 			return ret;
25725ca02815Sjsg 	}
25735ca02815Sjsg 	return ret;
25745ca02815Sjsg }
25755ca02815Sjsg 
25765ca02815Sjsg static int psp_load_non_psp_fw(struct psp_context *psp)
2577ad8b1aafSjsg {
2578ad8b1aafSjsg 	int i, ret;
2579ad8b1aafSjsg 	struct amdgpu_firmware_info *ucode;
2580ad8b1aafSjsg 	struct amdgpu_device *adev = psp->adev;
2581ad8b1aafSjsg 
2582ad8b1aafSjsg 	if (psp->autoload_supported &&
2583ad8b1aafSjsg 	    !psp->pmfw_centralized_cstate_management) {
2584ad8b1aafSjsg 		ret = psp_load_smu_fw(psp);
2585ad8b1aafSjsg 		if (ret)
2586ad8b1aafSjsg 			return ret;
2587ad8b1aafSjsg 	}
2588ad8b1aafSjsg 
2589ad8b1aafSjsg 	for (i = 0; i < adev->firmware.max_ucodes; i++) {
2590ad8b1aafSjsg 		ucode = &adev->firmware.ucode[i];
2591ad8b1aafSjsg 
2592ad8b1aafSjsg 		if (ucode->ucode_id == AMDGPU_UCODE_ID_SMC &&
2593ad8b1aafSjsg 		    !fw_load_skip_check(psp, ucode)) {
2594ad8b1aafSjsg 			ret = psp_load_smu_fw(psp);
2595ad8b1aafSjsg 			if (ret)
2596ad8b1aafSjsg 				return ret;
2597ad8b1aafSjsg 			continue;
2598ad8b1aafSjsg 		}
2599ad8b1aafSjsg 
2600ad8b1aafSjsg 		if (fw_load_skip_check(psp, ucode))
2601ad8b1aafSjsg 			continue;
2602ad8b1aafSjsg 
2603ad8b1aafSjsg 		if (psp->autoload_supported &&
26041bb76ff1Sjsg 		    (adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 7) ||
26051bb76ff1Sjsg 		     adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 11) ||
26061bb76ff1Sjsg 		     adev->ip_versions[MP0_HWIP][0] == IP_VERSION(11, 0, 12)) &&
2607ad8b1aafSjsg 		    (ucode->ucode_id == AMDGPU_UCODE_ID_SDMA1 ||
2608ad8b1aafSjsg 		     ucode->ucode_id == AMDGPU_UCODE_ID_SDMA2 ||
2609ad8b1aafSjsg 		     ucode->ucode_id == AMDGPU_UCODE_ID_SDMA3))
2610ad8b1aafSjsg 			/* PSP only receive one SDMA fw for sienna_cichlid,
2611f005ef32Sjsg 			 * as all four sdma fw are same
2612f005ef32Sjsg 			 */
2613c349dbc7Sjsg 			continue;
2614c349dbc7Sjsg 
2615c349dbc7Sjsg 		psp_print_fw_hdr(psp, ucode);
2616c349dbc7Sjsg 
2617f005ef32Sjsg 		ret = psp_execute_ip_fw_load(psp, ucode);
2618fb4d8502Sjsg 		if (ret)
2619fb4d8502Sjsg 			return ret;
2620fb4d8502Sjsg 
2621c349dbc7Sjsg 		/* Start rlc autoload after psp recieved all the gfx firmware */
2622c349dbc7Sjsg 		if (psp->autoload_supported && ucode->ucode_id == (amdgpu_sriov_vf(adev) ?
26231bb76ff1Sjsg 		    adev->virt.autoload_ucode_id : AMDGPU_UCODE_ID_RLC_G)) {
2624ad8b1aafSjsg 			ret = psp_rlc_autoload_start(psp);
2625c349dbc7Sjsg 			if (ret) {
2626c349dbc7Sjsg 				DRM_ERROR("Failed to start rlc autoload\n");
2627fb4d8502Sjsg 				return ret;
2628c349dbc7Sjsg 			}
2629c349dbc7Sjsg 		}
2630fb4d8502Sjsg 	}
2631fb4d8502Sjsg 
2632fb4d8502Sjsg 	return 0;
2633fb4d8502Sjsg }
2634fb4d8502Sjsg 
2635fb4d8502Sjsg static int psp_load_fw(struct amdgpu_device *adev)
2636fb4d8502Sjsg {
2637fb4d8502Sjsg 	int ret;
2638fb4d8502Sjsg 	struct psp_context *psp = &adev->psp;
2639fb4d8502Sjsg 
2640ad8b1aafSjsg 	if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) {
26410ae6e948Sjsg 		/* should not destroy ring, only stop */
26420ae6e948Sjsg 		psp_ring_stop(psp, PSP_RING_TYPE__KM);
26435ca02815Sjsg 	} else {
2644fb4d8502Sjsg 		memset(psp->fence_buf, 0, PSP_FENCE_BUFFER_SIZE);
2645fb4d8502Sjsg 
2646fb4d8502Sjsg 		ret = psp_ring_init(psp, PSP_RING_TYPE__KM);
2647c349dbc7Sjsg 		if (ret) {
2648c349dbc7Sjsg 			DRM_ERROR("PSP ring init failed!\n");
2649c349dbc7Sjsg 			goto failed;
2650c349dbc7Sjsg 		}
26510ae6e948Sjsg 	}
2652fb4d8502Sjsg 
2653fb4d8502Sjsg 	ret = psp_hw_start(psp);
2654fb4d8502Sjsg 	if (ret)
2655c349dbc7Sjsg 		goto failed;
2656fb4d8502Sjsg 
26575ca02815Sjsg 	ret = psp_load_non_psp_fw(psp);
2658fb4d8502Sjsg 	if (ret)
26591bb76ff1Sjsg 		goto failed1;
2660c349dbc7Sjsg 
26611bb76ff1Sjsg 	ret = psp_asd_initialize(psp);
2662c349dbc7Sjsg 	if (ret) {
2663c349dbc7Sjsg 		DRM_ERROR("PSP load asd failed!\n");
26641bb76ff1Sjsg 		goto failed1;
2665c349dbc7Sjsg 	}
2666c349dbc7Sjsg 
26675ca02815Sjsg 	ret = psp_rl_load(adev);
26685ca02815Sjsg 	if (ret) {
26695ca02815Sjsg 		DRM_ERROR("PSP load RL failed!\n");
26701bb76ff1Sjsg 		goto failed1;
26711bb76ff1Sjsg 	}
26721bb76ff1Sjsg 
26731bb76ff1Sjsg 	if (amdgpu_sriov_vf(adev) && amdgpu_in_reset(adev)) {
26741bb76ff1Sjsg 		if (adev->gmc.xgmi.num_physical_nodes > 1) {
26751bb76ff1Sjsg 			ret = psp_xgmi_initialize(psp, false, true);
26761bb76ff1Sjsg 			/* Warning the XGMI seesion initialize failure
26771bb76ff1Sjsg 			 * Instead of stop driver initialization
26781bb76ff1Sjsg 			 */
26791bb76ff1Sjsg 			if (ret)
26801bb76ff1Sjsg 				dev_err(psp->adev->dev,
26811bb76ff1Sjsg 					"XGMI: Failed to initialize XGMI session\n");
26821bb76ff1Sjsg 		}
26835ca02815Sjsg 	}
26845ca02815Sjsg 
26855ca02815Sjsg 	if (psp->ta_fw) {
2686c349dbc7Sjsg 		ret = psp_ras_initialize(psp);
2687c349dbc7Sjsg 		if (ret)
2688c349dbc7Sjsg 			dev_err(psp->adev->dev,
2689c349dbc7Sjsg 					"RAS: Failed to initialize RAS\n");
2690c349dbc7Sjsg 
2691c349dbc7Sjsg 		ret = psp_hdcp_initialize(psp);
2692c349dbc7Sjsg 		if (ret)
2693c349dbc7Sjsg 			dev_err(psp->adev->dev,
2694c349dbc7Sjsg 				"HDCP: Failed to initialize HDCP\n");
2695c349dbc7Sjsg 
2696c349dbc7Sjsg 		ret = psp_dtm_initialize(psp);
2697c349dbc7Sjsg 		if (ret)
2698c349dbc7Sjsg 			dev_err(psp->adev->dev,
2699c349dbc7Sjsg 				"DTM: Failed to initialize DTM\n");
2700ad8b1aafSjsg 
2701ad8b1aafSjsg 		ret = psp_rap_initialize(psp);
2702ad8b1aafSjsg 		if (ret)
2703ad8b1aafSjsg 			dev_err(psp->adev->dev,
2704ad8b1aafSjsg 				"RAP: Failed to initialize RAP\n");
27055ca02815Sjsg 
27065ca02815Sjsg 		ret = psp_securedisplay_initialize(psp);
27075ca02815Sjsg 		if (ret)
27085ca02815Sjsg 			dev_err(psp->adev->dev,
27095ca02815Sjsg 				"SECUREDISPLAY: Failed to initialize SECUREDISPLAY\n");
2710c349dbc7Sjsg 	}
2711fb4d8502Sjsg 
2712fb4d8502Sjsg 	return 0;
2713fb4d8502Sjsg 
27141bb76ff1Sjsg failed1:
27151bb76ff1Sjsg 	psp_free_shared_bufs(psp);
2716fb4d8502Sjsg failed:
2717c349dbc7Sjsg 	/*
2718c349dbc7Sjsg 	 * all cleanup jobs (xgmi terminate, ras terminate,
2719c349dbc7Sjsg 	 * ring destroy, cmd/fence/fw buffers destory,
2720c349dbc7Sjsg 	 * psp->cmd destory) are delayed to psp_hw_fini
2721c349dbc7Sjsg 	 */
27221bb76ff1Sjsg 	psp_ring_destroy(psp, PSP_RING_TYPE__KM);
2723fb4d8502Sjsg 	return ret;
2724fb4d8502Sjsg }
2725fb4d8502Sjsg 
2726fb4d8502Sjsg static int psp_hw_init(void *handle)
2727fb4d8502Sjsg {
2728fb4d8502Sjsg 	int ret;
2729fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2730fb4d8502Sjsg 
2731fb4d8502Sjsg 	mutex_lock(&adev->firmware.mutex);
2732fb4d8502Sjsg 	/*
2733fb4d8502Sjsg 	 * This sequence is just used on hw_init only once, no need on
2734fb4d8502Sjsg 	 * resume.
2735fb4d8502Sjsg 	 */
2736fb4d8502Sjsg 	ret = amdgpu_ucode_init_bo(adev);
2737fb4d8502Sjsg 	if (ret)
2738fb4d8502Sjsg 		goto failed;
2739fb4d8502Sjsg 
2740fb4d8502Sjsg 	ret = psp_load_fw(adev);
2741fb4d8502Sjsg 	if (ret) {
2742fb4d8502Sjsg 		DRM_ERROR("PSP firmware loading failed\n");
2743fb4d8502Sjsg 		goto failed;
2744fb4d8502Sjsg 	}
2745fb4d8502Sjsg 
2746fb4d8502Sjsg 	mutex_unlock(&adev->firmware.mutex);
2747fb4d8502Sjsg 	return 0;
2748fb4d8502Sjsg 
2749fb4d8502Sjsg failed:
2750fb4d8502Sjsg 	adev->firmware.load_type = AMDGPU_FW_LOAD_DIRECT;
2751fb4d8502Sjsg 	mutex_unlock(&adev->firmware.mutex);
2752fb4d8502Sjsg 	return -EINVAL;
2753fb4d8502Sjsg }
2754fb4d8502Sjsg 
2755fb4d8502Sjsg static int psp_hw_fini(void *handle)
2756fb4d8502Sjsg {
2757fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2758fb4d8502Sjsg 	struct psp_context *psp = &adev->psp;
2759fb4d8502Sjsg 
27605ca02815Sjsg 	if (psp->ta_fw) {
2761c349dbc7Sjsg 		psp_ras_terminate(psp);
27625ca02815Sjsg 		psp_securedisplay_terminate(psp);
2763ad8b1aafSjsg 		psp_rap_terminate(psp);
2764c349dbc7Sjsg 		psp_dtm_terminate(psp);
2765c349dbc7Sjsg 		psp_hdcp_terminate(psp);
2766f8d078a0Sjsg 
2767f8d078a0Sjsg 		if (adev->gmc.xgmi.num_physical_nodes > 1)
2768f8d078a0Sjsg 			psp_xgmi_terminate(psp);
2769c349dbc7Sjsg 	}
2770fb4d8502Sjsg 
27711bb76ff1Sjsg 	psp_asd_terminate(psp);
27726bd9a77dSjsg 	psp_tmr_terminate(psp);
27731bb76ff1Sjsg 
2774fb4d8502Sjsg 	psp_ring_destroy(psp, PSP_RING_TYPE__KM);
2775fb4d8502Sjsg 
2776fb4d8502Sjsg 	return 0;
2777fb4d8502Sjsg }
2778fb4d8502Sjsg 
2779fb4d8502Sjsg static int psp_suspend(void *handle)
2780fb4d8502Sjsg {
27811bb76ff1Sjsg 	int ret = 0;
2782fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2783fb4d8502Sjsg 	struct psp_context *psp = &adev->psp;
2784fb4d8502Sjsg 
2785c349dbc7Sjsg 	if (adev->gmc.xgmi.num_physical_nodes > 1 &&
27865ca02815Sjsg 	    psp->xgmi_context.context.initialized) {
2787c349dbc7Sjsg 		ret = psp_xgmi_terminate(psp);
2788c349dbc7Sjsg 		if (ret) {
2789c349dbc7Sjsg 			DRM_ERROR("Failed to terminate xgmi ta\n");
27901bb76ff1Sjsg 			goto out;
2791c349dbc7Sjsg 		}
2792c349dbc7Sjsg 	}
2793c349dbc7Sjsg 
27945ca02815Sjsg 	if (psp->ta_fw) {
2795c349dbc7Sjsg 		ret = psp_ras_terminate(psp);
2796c349dbc7Sjsg 		if (ret) {
2797c349dbc7Sjsg 			DRM_ERROR("Failed to terminate ras ta\n");
27981bb76ff1Sjsg 			goto out;
2799c349dbc7Sjsg 		}
2800c349dbc7Sjsg 		ret = psp_hdcp_terminate(psp);
2801c349dbc7Sjsg 		if (ret) {
2802c349dbc7Sjsg 			DRM_ERROR("Failed to terminate hdcp ta\n");
28031bb76ff1Sjsg 			goto out;
2804c349dbc7Sjsg 		}
2805c349dbc7Sjsg 		ret = psp_dtm_terminate(psp);
2806c349dbc7Sjsg 		if (ret) {
2807c349dbc7Sjsg 			DRM_ERROR("Failed to terminate dtm ta\n");
28081bb76ff1Sjsg 			goto out;
2809c349dbc7Sjsg 		}
2810ad8b1aafSjsg 		ret = psp_rap_terminate(psp);
2811ad8b1aafSjsg 		if (ret) {
2812ad8b1aafSjsg 			DRM_ERROR("Failed to terminate rap ta\n");
28131bb76ff1Sjsg 			goto out;
2814ad8b1aafSjsg 		}
28155ca02815Sjsg 		ret = psp_securedisplay_terminate(psp);
28165ca02815Sjsg 		if (ret) {
28175ca02815Sjsg 			DRM_ERROR("Failed to terminate securedisplay ta\n");
28181bb76ff1Sjsg 			goto out;
28195ca02815Sjsg 		}
2820c349dbc7Sjsg 	}
2821fb4d8502Sjsg 
28221bb76ff1Sjsg 	ret = psp_asd_terminate(psp);
282328304a26Sjsg 	if (ret) {
28241bb76ff1Sjsg 		DRM_ERROR("Failed to terminate asd\n");
28251bb76ff1Sjsg 		goto out;
282628304a26Sjsg 	}
282728304a26Sjsg 
28284aa0689aSjsg 	ret = psp_tmr_terminate(psp);
28294aa0689aSjsg 	if (ret) {
2830ad8b1aafSjsg 		DRM_ERROR("Failed to terminate tmr\n");
28311bb76ff1Sjsg 		goto out;
28324aa0689aSjsg 	}
28334aa0689aSjsg 
2834fb4d8502Sjsg 	ret = psp_ring_stop(psp, PSP_RING_TYPE__KM);
2835f005ef32Sjsg 	if (ret)
2836fb4d8502Sjsg 		DRM_ERROR("PSP ring stop failed\n");
2837fb4d8502Sjsg 
28381bb76ff1Sjsg out:
28391bb76ff1Sjsg 	return ret;
2840fb4d8502Sjsg }
2841fb4d8502Sjsg 
2842fb4d8502Sjsg static int psp_resume(void *handle)
2843fb4d8502Sjsg {
2844fb4d8502Sjsg 	int ret;
2845fb4d8502Sjsg 	struct amdgpu_device *adev = (struct amdgpu_device *)handle;
2846fb4d8502Sjsg 	struct psp_context *psp = &adev->psp;
2847fb4d8502Sjsg 
2848fb4d8502Sjsg 	DRM_INFO("PSP is resuming...\n");
2849fb4d8502Sjsg 
28505ca02815Sjsg 	if (psp->mem_train_ctx.enable_mem_training) {
2851c349dbc7Sjsg 		ret = psp_mem_training(psp, PSP_MEM_TRAIN_RESUME);
2852c349dbc7Sjsg 		if (ret) {
2853c349dbc7Sjsg 			DRM_ERROR("Failed to process memory training!\n");
2854c349dbc7Sjsg 			return ret;
2855c349dbc7Sjsg 		}
28565ca02815Sjsg 	}
2857c349dbc7Sjsg 
2858fb4d8502Sjsg 	mutex_lock(&adev->firmware.mutex);
2859fb4d8502Sjsg 
2860fb4d8502Sjsg 	ret = psp_hw_start(psp);
2861fb4d8502Sjsg 	if (ret)
2862fb4d8502Sjsg 		goto failed;
2863fb4d8502Sjsg 
28645ca02815Sjsg 	ret = psp_load_non_psp_fw(psp);
2865fb4d8502Sjsg 	if (ret)
2866fb4d8502Sjsg 		goto failed;
2867fb4d8502Sjsg 
28681bb76ff1Sjsg 	ret = psp_asd_initialize(psp);
2869c349dbc7Sjsg 	if (ret) {
2870c349dbc7Sjsg 		DRM_ERROR("PSP load asd failed!\n");
2871c349dbc7Sjsg 		goto failed;
2872c349dbc7Sjsg 	}
2873c349dbc7Sjsg 
28741bb76ff1Sjsg 	ret = psp_rl_load(adev);
28751bb76ff1Sjsg 	if (ret) {
28761bb76ff1Sjsg 		dev_err(adev->dev, "PSP load RL failed!\n");
28771bb76ff1Sjsg 		goto failed;
28781bb76ff1Sjsg 	}
28791bb76ff1Sjsg 
2880c349dbc7Sjsg 	if (adev->gmc.xgmi.num_physical_nodes > 1) {
28815ca02815Sjsg 		ret = psp_xgmi_initialize(psp, false, true);
2882c349dbc7Sjsg 		/* Warning the XGMI seesion initialize failure
2883c349dbc7Sjsg 		 * Instead of stop driver initialization
2884c349dbc7Sjsg 		 */
2885c349dbc7Sjsg 		if (ret)
2886c349dbc7Sjsg 			dev_err(psp->adev->dev,
2887c349dbc7Sjsg 				"XGMI: Failed to initialize XGMI session\n");
2888c349dbc7Sjsg 	}
2889c349dbc7Sjsg 
28905ca02815Sjsg 	if (psp->ta_fw) {
2891c349dbc7Sjsg 		ret = psp_ras_initialize(psp);
2892c349dbc7Sjsg 		if (ret)
2893c349dbc7Sjsg 			dev_err(psp->adev->dev,
2894c349dbc7Sjsg 					"RAS: Failed to initialize RAS\n");
2895c349dbc7Sjsg 
2896c349dbc7Sjsg 		ret = psp_hdcp_initialize(psp);
2897c349dbc7Sjsg 		if (ret)
2898c349dbc7Sjsg 			dev_err(psp->adev->dev,
2899c349dbc7Sjsg 				"HDCP: Failed to initialize HDCP\n");
2900c349dbc7Sjsg 
2901c349dbc7Sjsg 		ret = psp_dtm_initialize(psp);
2902c349dbc7Sjsg 		if (ret)
2903c349dbc7Sjsg 			dev_err(psp->adev->dev,
2904c349dbc7Sjsg 				"DTM: Failed to initialize DTM\n");
2905ad8b1aafSjsg 
2906ad8b1aafSjsg 		ret = psp_rap_initialize(psp);
2907ad8b1aafSjsg 		if (ret)
2908ad8b1aafSjsg 			dev_err(psp->adev->dev,
2909ad8b1aafSjsg 				"RAP: Failed to initialize RAP\n");
29105ca02815Sjsg 
29115ca02815Sjsg 		ret = psp_securedisplay_initialize(psp);
29125ca02815Sjsg 		if (ret)
29135ca02815Sjsg 			dev_err(psp->adev->dev,
29145ca02815Sjsg 				"SECUREDISPLAY: Failed to initialize SECUREDISPLAY\n");
2915c349dbc7Sjsg 	}
2916c349dbc7Sjsg 
2917fb4d8502Sjsg 	mutex_unlock(&adev->firmware.mutex);
2918fb4d8502Sjsg 
2919fb4d8502Sjsg 	return 0;
2920fb4d8502Sjsg 
2921fb4d8502Sjsg failed:
2922fb4d8502Sjsg 	DRM_ERROR("PSP resume failed\n");
2923fb4d8502Sjsg 	mutex_unlock(&adev->firmware.mutex);
2924fb4d8502Sjsg 	return ret;
2925fb4d8502Sjsg }
2926fb4d8502Sjsg 
2927fb4d8502Sjsg int psp_gpu_reset(struct amdgpu_device *adev)
2928fb4d8502Sjsg {
2929c349dbc7Sjsg 	int ret;
2930c349dbc7Sjsg 
2931fb4d8502Sjsg 	if (adev->firmware.load_type != AMDGPU_FW_LOAD_PSP)
2932fb4d8502Sjsg 		return 0;
2933fb4d8502Sjsg 
2934c349dbc7Sjsg 	mutex_lock(&adev->psp.mutex);
2935c349dbc7Sjsg 	ret = psp_mode1_reset(&adev->psp);
2936c349dbc7Sjsg 	mutex_unlock(&adev->psp.mutex);
2937c349dbc7Sjsg 
2938c349dbc7Sjsg 	return ret;
2939c349dbc7Sjsg }
2940c349dbc7Sjsg 
2941c349dbc7Sjsg int psp_rlc_autoload_start(struct psp_context *psp)
2942c349dbc7Sjsg {
2943c349dbc7Sjsg 	int ret;
29445ca02815Sjsg 	struct psp_gfx_cmd_resp *cmd = acquire_psp_cmd_buf(psp);
2945c349dbc7Sjsg 
2946c349dbc7Sjsg 	cmd->cmd_id = GFX_CMD_ID_AUTOLOAD_RLC;
2947c349dbc7Sjsg 
2948c349dbc7Sjsg 	ret = psp_cmd_submit_buf(psp, NULL, cmd,
2949c349dbc7Sjsg 				 psp->fence_buf_mc_addr);
29505ca02815Sjsg 
29515ca02815Sjsg 	release_psp_cmd_buf(psp);
29525ca02815Sjsg 
2953c349dbc7Sjsg 	return ret;
2954c349dbc7Sjsg }
2955c349dbc7Sjsg 
2956c349dbc7Sjsg int psp_ring_cmd_submit(struct psp_context *psp,
2957c349dbc7Sjsg 			uint64_t cmd_buf_mc_addr,
2958c349dbc7Sjsg 			uint64_t fence_mc_addr,
2959c349dbc7Sjsg 			int index)
2960c349dbc7Sjsg {
2961c349dbc7Sjsg 	unsigned int psp_write_ptr_reg = 0;
2962c349dbc7Sjsg 	struct psp_gfx_rb_frame *write_frame;
2963c349dbc7Sjsg 	struct psp_ring *ring = &psp->km_ring;
2964c349dbc7Sjsg 	struct psp_gfx_rb_frame *ring_buffer_start = ring->ring_mem;
2965c349dbc7Sjsg 	struct psp_gfx_rb_frame *ring_buffer_end = ring_buffer_start +
2966c349dbc7Sjsg 		ring->ring_size / sizeof(struct psp_gfx_rb_frame) - 1;
2967c349dbc7Sjsg 	struct amdgpu_device *adev = psp->adev;
2968c349dbc7Sjsg 	uint32_t ring_size_dw = ring->ring_size / 4;
2969c349dbc7Sjsg 	uint32_t rb_frame_size_dw = sizeof(struct psp_gfx_rb_frame) / 4;
2970c349dbc7Sjsg 
2971c349dbc7Sjsg 	/* KM (GPCOM) prepare write pointer */
2972c349dbc7Sjsg 	psp_write_ptr_reg = psp_ring_get_wptr(psp);
2973c349dbc7Sjsg 
2974c349dbc7Sjsg 	/* Update KM RB frame pointer to new frame */
2975c349dbc7Sjsg 	/* write_frame ptr increments by size of rb_frame in bytes */
2976c349dbc7Sjsg 	/* psp_write_ptr_reg increments by size of rb_frame in DWORDs */
2977c349dbc7Sjsg 	if ((psp_write_ptr_reg % ring_size_dw) == 0)
2978c349dbc7Sjsg 		write_frame = ring_buffer_start;
2979c349dbc7Sjsg 	else
2980c349dbc7Sjsg 		write_frame = ring_buffer_start + (psp_write_ptr_reg / rb_frame_size_dw);
2981c349dbc7Sjsg 	/* Check invalid write_frame ptr address */
2982c349dbc7Sjsg 	if ((write_frame < ring_buffer_start) || (ring_buffer_end < write_frame)) {
2983c349dbc7Sjsg 		DRM_ERROR("ring_buffer_start = %p; ring_buffer_end = %p; write_frame = %p\n",
2984c349dbc7Sjsg 			  ring_buffer_start, ring_buffer_end, write_frame);
2985c349dbc7Sjsg 		DRM_ERROR("write_frame is pointing to address out of bounds\n");
2986c349dbc7Sjsg 		return -EINVAL;
2987c349dbc7Sjsg 	}
2988c349dbc7Sjsg 
2989c349dbc7Sjsg 	/* Initialize KM RB frame */
2990c349dbc7Sjsg 	memset(write_frame, 0, sizeof(struct psp_gfx_rb_frame));
2991c349dbc7Sjsg 
2992c349dbc7Sjsg 	/* Update KM RB frame */
2993c349dbc7Sjsg 	write_frame->cmd_buf_addr_hi = upper_32_bits(cmd_buf_mc_addr);
2994c349dbc7Sjsg 	write_frame->cmd_buf_addr_lo = lower_32_bits(cmd_buf_mc_addr);
2995c349dbc7Sjsg 	write_frame->fence_addr_hi = upper_32_bits(fence_mc_addr);
2996c349dbc7Sjsg 	write_frame->fence_addr_lo = lower_32_bits(fence_mc_addr);
2997c349dbc7Sjsg 	write_frame->fence_value = index;
29985ca02815Sjsg 	amdgpu_device_flush_hdp(adev, NULL);
2999c349dbc7Sjsg 
3000c349dbc7Sjsg 	/* Update the write Pointer in DWORDs */
3001c349dbc7Sjsg 	psp_write_ptr_reg = (psp_write_ptr_reg + rb_frame_size_dw) % ring_size_dw;
3002c349dbc7Sjsg 	psp_ring_set_wptr(psp, psp_write_ptr_reg);
3003c349dbc7Sjsg 	return 0;
3004fb4d8502Sjsg }
3005fb4d8502Sjsg 
3006f005ef32Sjsg int psp_init_asd_microcode(struct psp_context *psp, const char *chip_name)
3007fb4d8502Sjsg {
3008ad8b1aafSjsg 	struct amdgpu_device *adev = psp->adev;
30095ca02815Sjsg 	char fw_name[PSP_FW_NAME_LEN];
3010ad8b1aafSjsg 	const struct psp_firmware_header_v1_0 *asd_hdr;
3011ad8b1aafSjsg 	int err = 0;
3012fb4d8502Sjsg 
3013ad8b1aafSjsg 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_asd.bin", chip_name);
3014f005ef32Sjsg 	err = amdgpu_ucode_request(adev, &adev->psp.asd_fw, fw_name);
3015ad8b1aafSjsg 	if (err)
3016ad8b1aafSjsg 		goto out;
3017ad8b1aafSjsg 
3018ad8b1aafSjsg 	asd_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.asd_fw->data;
30191bb76ff1Sjsg 	adev->psp.asd_context.bin_desc.fw_version = le32_to_cpu(asd_hdr->header.ucode_version);
30201bb76ff1Sjsg 	adev->psp.asd_context.bin_desc.feature_version = le32_to_cpu(asd_hdr->sos.fw_version);
30211bb76ff1Sjsg 	adev->psp.asd_context.bin_desc.size_bytes = le32_to_cpu(asd_hdr->header.ucode_size_bytes);
30221bb76ff1Sjsg 	adev->psp.asd_context.bin_desc.start_addr = (uint8_t *)asd_hdr +
3023ad8b1aafSjsg 				le32_to_cpu(asd_hdr->header.ucode_array_offset_bytes);
3024ad8b1aafSjsg 	return 0;
3025ad8b1aafSjsg out:
3026f005ef32Sjsg 	amdgpu_ucode_release(&adev->psp.asd_fw);
3027ad8b1aafSjsg 	return err;
3028ad8b1aafSjsg }
3029ad8b1aafSjsg 
3030f005ef32Sjsg int psp_init_toc_microcode(struct psp_context *psp, const char *chip_name)
30315ca02815Sjsg {
30325ca02815Sjsg 	struct amdgpu_device *adev = psp->adev;
30335ca02815Sjsg 	char fw_name[PSP_FW_NAME_LEN];
30345ca02815Sjsg 	const struct psp_firmware_header_v1_0 *toc_hdr;
30355ca02815Sjsg 	int err = 0;
30365ca02815Sjsg 
30375ca02815Sjsg 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_toc.bin", chip_name);
3038f005ef32Sjsg 	err = amdgpu_ucode_request(adev, &adev->psp.toc_fw, fw_name);
30395ca02815Sjsg 	if (err)
30405ca02815Sjsg 		goto out;
30415ca02815Sjsg 
30425ca02815Sjsg 	toc_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.toc_fw->data;
30435ca02815Sjsg 	adev->psp.toc.fw_version = le32_to_cpu(toc_hdr->header.ucode_version);
30445ca02815Sjsg 	adev->psp.toc.feature_version = le32_to_cpu(toc_hdr->sos.fw_version);
30455ca02815Sjsg 	adev->psp.toc.size_bytes = le32_to_cpu(toc_hdr->header.ucode_size_bytes);
30465ca02815Sjsg 	adev->psp.toc.start_addr = (uint8_t *)toc_hdr +
30475ca02815Sjsg 				le32_to_cpu(toc_hdr->header.ucode_array_offset_bytes);
30485ca02815Sjsg 	return 0;
30495ca02815Sjsg out:
3050f005ef32Sjsg 	amdgpu_ucode_release(&adev->psp.toc_fw);
30515ca02815Sjsg 	return err;
30525ca02815Sjsg }
30535ca02815Sjsg 
30545ca02815Sjsg static int parse_sos_bin_descriptor(struct psp_context *psp,
30555ca02815Sjsg 				   const struct psp_fw_bin_desc *desc,
30565ca02815Sjsg 				   const struct psp_firmware_header_v2_0 *sos_hdr)
30575ca02815Sjsg {
30585ca02815Sjsg 	uint8_t *ucode_start_addr  = NULL;
30595ca02815Sjsg 
30605ca02815Sjsg 	if (!psp || !desc || !sos_hdr)
30615ca02815Sjsg 		return -EINVAL;
30625ca02815Sjsg 
30635ca02815Sjsg 	ucode_start_addr  = (uint8_t *)sos_hdr +
30645ca02815Sjsg 			    le32_to_cpu(desc->offset_bytes) +
30655ca02815Sjsg 			    le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
30665ca02815Sjsg 
30675ca02815Sjsg 	switch (desc->fw_type) {
30685ca02815Sjsg 	case PSP_FW_TYPE_PSP_SOS:
30695ca02815Sjsg 		psp->sos.fw_version        = le32_to_cpu(desc->fw_version);
30705ca02815Sjsg 		psp->sos.feature_version   = le32_to_cpu(desc->fw_version);
30715ca02815Sjsg 		psp->sos.size_bytes        = le32_to_cpu(desc->size_bytes);
30725ca02815Sjsg 		psp->sos.start_addr	   = ucode_start_addr;
30735ca02815Sjsg 		break;
30745ca02815Sjsg 	case PSP_FW_TYPE_PSP_SYS_DRV:
30755ca02815Sjsg 		psp->sys.fw_version        = le32_to_cpu(desc->fw_version);
30765ca02815Sjsg 		psp->sys.feature_version   = le32_to_cpu(desc->fw_version);
30775ca02815Sjsg 		psp->sys.size_bytes        = le32_to_cpu(desc->size_bytes);
30785ca02815Sjsg 		psp->sys.start_addr        = ucode_start_addr;
30795ca02815Sjsg 		break;
30805ca02815Sjsg 	case PSP_FW_TYPE_PSP_KDB:
30815ca02815Sjsg 		psp->kdb.fw_version        = le32_to_cpu(desc->fw_version);
30825ca02815Sjsg 		psp->kdb.feature_version   = le32_to_cpu(desc->fw_version);
30835ca02815Sjsg 		psp->kdb.size_bytes        = le32_to_cpu(desc->size_bytes);
30845ca02815Sjsg 		psp->kdb.start_addr        = ucode_start_addr;
30855ca02815Sjsg 		break;
30865ca02815Sjsg 	case PSP_FW_TYPE_PSP_TOC:
30875ca02815Sjsg 		psp->toc.fw_version        = le32_to_cpu(desc->fw_version);
30885ca02815Sjsg 		psp->toc.feature_version   = le32_to_cpu(desc->fw_version);
30895ca02815Sjsg 		psp->toc.size_bytes        = le32_to_cpu(desc->size_bytes);
30905ca02815Sjsg 		psp->toc.start_addr        = ucode_start_addr;
30915ca02815Sjsg 		break;
30925ca02815Sjsg 	case PSP_FW_TYPE_PSP_SPL:
30935ca02815Sjsg 		psp->spl.fw_version        = le32_to_cpu(desc->fw_version);
30945ca02815Sjsg 		psp->spl.feature_version   = le32_to_cpu(desc->fw_version);
30955ca02815Sjsg 		psp->spl.size_bytes        = le32_to_cpu(desc->size_bytes);
30965ca02815Sjsg 		psp->spl.start_addr        = ucode_start_addr;
30975ca02815Sjsg 		break;
30985ca02815Sjsg 	case PSP_FW_TYPE_PSP_RL:
30995ca02815Sjsg 		psp->rl.fw_version         = le32_to_cpu(desc->fw_version);
31005ca02815Sjsg 		psp->rl.feature_version    = le32_to_cpu(desc->fw_version);
31015ca02815Sjsg 		psp->rl.size_bytes         = le32_to_cpu(desc->size_bytes);
31025ca02815Sjsg 		psp->rl.start_addr         = ucode_start_addr;
31035ca02815Sjsg 		break;
31045ca02815Sjsg 	case PSP_FW_TYPE_PSP_SOC_DRV:
31055ca02815Sjsg 		psp->soc_drv.fw_version         = le32_to_cpu(desc->fw_version);
31065ca02815Sjsg 		psp->soc_drv.feature_version    = le32_to_cpu(desc->fw_version);
31075ca02815Sjsg 		psp->soc_drv.size_bytes         = le32_to_cpu(desc->size_bytes);
31085ca02815Sjsg 		psp->soc_drv.start_addr         = ucode_start_addr;
31095ca02815Sjsg 		break;
31105ca02815Sjsg 	case PSP_FW_TYPE_PSP_INTF_DRV:
31115ca02815Sjsg 		psp->intf_drv.fw_version        = le32_to_cpu(desc->fw_version);
31125ca02815Sjsg 		psp->intf_drv.feature_version   = le32_to_cpu(desc->fw_version);
31135ca02815Sjsg 		psp->intf_drv.size_bytes        = le32_to_cpu(desc->size_bytes);
31145ca02815Sjsg 		psp->intf_drv.start_addr        = ucode_start_addr;
31155ca02815Sjsg 		break;
31165ca02815Sjsg 	case PSP_FW_TYPE_PSP_DBG_DRV:
31175ca02815Sjsg 		psp->dbg_drv.fw_version         = le32_to_cpu(desc->fw_version);
31185ca02815Sjsg 		psp->dbg_drv.feature_version    = le32_to_cpu(desc->fw_version);
31195ca02815Sjsg 		psp->dbg_drv.size_bytes         = le32_to_cpu(desc->size_bytes);
31205ca02815Sjsg 		psp->dbg_drv.start_addr         = ucode_start_addr;
31215ca02815Sjsg 		break;
31221bb76ff1Sjsg 	case PSP_FW_TYPE_PSP_RAS_DRV:
31231bb76ff1Sjsg 		psp->ras_drv.fw_version         = le32_to_cpu(desc->fw_version);
31241bb76ff1Sjsg 		psp->ras_drv.feature_version    = le32_to_cpu(desc->fw_version);
31251bb76ff1Sjsg 		psp->ras_drv.size_bytes         = le32_to_cpu(desc->size_bytes);
31261bb76ff1Sjsg 		psp->ras_drv.start_addr         = ucode_start_addr;
31271bb76ff1Sjsg 		break;
31285ca02815Sjsg 	default:
31295ca02815Sjsg 		dev_warn(psp->adev->dev, "Unsupported PSP FW type: %d\n", desc->fw_type);
31305ca02815Sjsg 		break;
31315ca02815Sjsg 	}
31325ca02815Sjsg 
31335ca02815Sjsg 	return 0;
31345ca02815Sjsg }
31355ca02815Sjsg 
31365ca02815Sjsg static int psp_init_sos_base_fw(struct amdgpu_device *adev)
31375ca02815Sjsg {
31385ca02815Sjsg 	const struct psp_firmware_header_v1_0 *sos_hdr;
31395ca02815Sjsg 	const struct psp_firmware_header_v1_3 *sos_hdr_v1_3;
31405ca02815Sjsg 	uint8_t *ucode_array_start_addr;
31415ca02815Sjsg 
31425ca02815Sjsg 	sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data;
31435ca02815Sjsg 	ucode_array_start_addr = (uint8_t *)sos_hdr +
31445ca02815Sjsg 		le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
31455ca02815Sjsg 
31461bb76ff1Sjsg 	if (adev->gmc.xgmi.connected_to_cpu ||
31471bb76ff1Sjsg 	    (adev->ip_versions[MP0_HWIP][0] != IP_VERSION(13, 0, 2))) {
31485ca02815Sjsg 		adev->psp.sos.fw_version = le32_to_cpu(sos_hdr->header.ucode_version);
31495ca02815Sjsg 		adev->psp.sos.feature_version = le32_to_cpu(sos_hdr->sos.fw_version);
31505ca02815Sjsg 
31515ca02815Sjsg 		adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr->sos.offset_bytes);
31525ca02815Sjsg 		adev->psp.sys.start_addr = ucode_array_start_addr;
31535ca02815Sjsg 
31545ca02815Sjsg 		adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr->sos.size_bytes);
31555ca02815Sjsg 		adev->psp.sos.start_addr = ucode_array_start_addr +
31565ca02815Sjsg 				le32_to_cpu(sos_hdr->sos.offset_bytes);
31575ca02815Sjsg 	} else {
31585ca02815Sjsg 		/* Load alternate PSP SOS FW */
31595ca02815Sjsg 		sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
31605ca02815Sjsg 
31615ca02815Sjsg 		adev->psp.sos.fw_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
31625ca02815Sjsg 		adev->psp.sos.feature_version = le32_to_cpu(sos_hdr_v1_3->sos_aux.fw_version);
31635ca02815Sjsg 
31645ca02815Sjsg 		adev->psp.sys.size_bytes = le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.size_bytes);
31655ca02815Sjsg 		adev->psp.sys.start_addr = ucode_array_start_addr +
31665ca02815Sjsg 			le32_to_cpu(sos_hdr_v1_3->sys_drv_aux.offset_bytes);
31675ca02815Sjsg 
31685ca02815Sjsg 		adev->psp.sos.size_bytes = le32_to_cpu(sos_hdr_v1_3->sos_aux.size_bytes);
31695ca02815Sjsg 		adev->psp.sos.start_addr = ucode_array_start_addr +
31705ca02815Sjsg 			le32_to_cpu(sos_hdr_v1_3->sos_aux.offset_bytes);
31715ca02815Sjsg 	}
31725ca02815Sjsg 
31735ca02815Sjsg 	if ((adev->psp.sys.size_bytes == 0) || (adev->psp.sos.size_bytes == 0)) {
31745ca02815Sjsg 		dev_warn(adev->dev, "PSP SOS FW not available");
31755ca02815Sjsg 		return -EINVAL;
31765ca02815Sjsg 	}
31775ca02815Sjsg 
31785ca02815Sjsg 	return 0;
31795ca02815Sjsg }
31805ca02815Sjsg 
3181f005ef32Sjsg int psp_init_sos_microcode(struct psp_context *psp, const char *chip_name)
3182ad8b1aafSjsg {
3183ad8b1aafSjsg 	struct amdgpu_device *adev = psp->adev;
31845ca02815Sjsg 	char fw_name[PSP_FW_NAME_LEN];
3185ad8b1aafSjsg 	const struct psp_firmware_header_v1_0 *sos_hdr;
3186ad8b1aafSjsg 	const struct psp_firmware_header_v1_1 *sos_hdr_v1_1;
3187ad8b1aafSjsg 	const struct psp_firmware_header_v1_2 *sos_hdr_v1_2;
3188ad8b1aafSjsg 	const struct psp_firmware_header_v1_3 *sos_hdr_v1_3;
31895ca02815Sjsg 	const struct psp_firmware_header_v2_0 *sos_hdr_v2_0;
3190ad8b1aafSjsg 	int err = 0;
31915ca02815Sjsg 	uint8_t *ucode_array_start_addr;
31925ca02815Sjsg 	int fw_index = 0;
3193ad8b1aafSjsg 
3194ad8b1aafSjsg 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_sos.bin", chip_name);
3195f005ef32Sjsg 	err = amdgpu_ucode_request(adev, &adev->psp.sos_fw, fw_name);
3196ad8b1aafSjsg 	if (err)
3197ad8b1aafSjsg 		goto out;
3198ad8b1aafSjsg 
3199ad8b1aafSjsg 	sos_hdr = (const struct psp_firmware_header_v1_0 *)adev->psp.sos_fw->data;
32005ca02815Sjsg 	ucode_array_start_addr = (uint8_t *)sos_hdr +
32015ca02815Sjsg 		le32_to_cpu(sos_hdr->header.ucode_array_offset_bytes);
3202ad8b1aafSjsg 	amdgpu_ucode_print_psp_hdr(&sos_hdr->header);
3203ad8b1aafSjsg 
3204ad8b1aafSjsg 	switch (sos_hdr->header.header_version_major) {
3205ad8b1aafSjsg 	case 1:
32065ca02815Sjsg 		err = psp_init_sos_base_fw(adev);
32075ca02815Sjsg 		if (err)
32085ca02815Sjsg 			goto out;
32095ca02815Sjsg 
3210ad8b1aafSjsg 		if (sos_hdr->header.header_version_minor == 1) {
3211ad8b1aafSjsg 			sos_hdr_v1_1 = (const struct psp_firmware_header_v1_1 *)adev->psp.sos_fw->data;
32125ca02815Sjsg 			adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_1->toc.size_bytes);
32135ca02815Sjsg 			adev->psp.toc.start_addr = (uint8_t *)adev->psp.sys.start_addr +
32145ca02815Sjsg 					le32_to_cpu(sos_hdr_v1_1->toc.offset_bytes);
32155ca02815Sjsg 			adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_1->kdb.size_bytes);
32165ca02815Sjsg 			adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr +
32175ca02815Sjsg 					le32_to_cpu(sos_hdr_v1_1->kdb.offset_bytes);
3218ad8b1aafSjsg 		}
3219ad8b1aafSjsg 		if (sos_hdr->header.header_version_minor == 2) {
3220ad8b1aafSjsg 			sos_hdr_v1_2 = (const struct psp_firmware_header_v1_2 *)adev->psp.sos_fw->data;
32215ca02815Sjsg 			adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_2->kdb.size_bytes);
32225ca02815Sjsg 			adev->psp.kdb.start_addr = (uint8_t *)adev->psp.sys.start_addr +
32235ca02815Sjsg 						    le32_to_cpu(sos_hdr_v1_2->kdb.offset_bytes);
3224ad8b1aafSjsg 		}
3225ad8b1aafSjsg 		if (sos_hdr->header.header_version_minor == 3) {
3226ad8b1aafSjsg 			sos_hdr_v1_3 = (const struct psp_firmware_header_v1_3 *)adev->psp.sos_fw->data;
32275ca02815Sjsg 			adev->psp.toc.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.toc.size_bytes);
32285ca02815Sjsg 			adev->psp.toc.start_addr = ucode_array_start_addr +
32295ca02815Sjsg 				le32_to_cpu(sos_hdr_v1_3->v1_1.toc.offset_bytes);
32305ca02815Sjsg 			adev->psp.kdb.size_bytes = le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.size_bytes);
32315ca02815Sjsg 			adev->psp.kdb.start_addr = ucode_array_start_addr +
32325ca02815Sjsg 				le32_to_cpu(sos_hdr_v1_3->v1_1.kdb.offset_bytes);
32335ca02815Sjsg 			adev->psp.spl.size_bytes = le32_to_cpu(sos_hdr_v1_3->spl.size_bytes);
32345ca02815Sjsg 			adev->psp.spl.start_addr = ucode_array_start_addr +
32355ca02815Sjsg 				le32_to_cpu(sos_hdr_v1_3->spl.offset_bytes);
32365ca02815Sjsg 			adev->psp.rl.size_bytes = le32_to_cpu(sos_hdr_v1_3->rl.size_bytes);
32375ca02815Sjsg 			adev->psp.rl.start_addr = ucode_array_start_addr +
32385ca02815Sjsg 				le32_to_cpu(sos_hdr_v1_3->rl.offset_bytes);
32395ca02815Sjsg 		}
32405ca02815Sjsg 		break;
32415ca02815Sjsg 	case 2:
32425ca02815Sjsg 		sos_hdr_v2_0 = (const struct psp_firmware_header_v2_0 *)adev->psp.sos_fw->data;
32435ca02815Sjsg 
32445ca02815Sjsg 		if (le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
32455ca02815Sjsg 			dev_err(adev->dev, "packed SOS count exceeds maximum limit\n");
32465ca02815Sjsg 			err = -EINVAL;
32475ca02815Sjsg 			goto out;
32485ca02815Sjsg 		}
32495ca02815Sjsg 
32505ca02815Sjsg 		for (fw_index = 0; fw_index < le32_to_cpu(sos_hdr_v2_0->psp_fw_bin_count); fw_index++) {
32515ca02815Sjsg 			err = parse_sos_bin_descriptor(psp,
32525ca02815Sjsg 						       &sos_hdr_v2_0->psp_fw_bin[fw_index],
32535ca02815Sjsg 						       sos_hdr_v2_0);
32545ca02815Sjsg 			if (err)
32555ca02815Sjsg 				goto out;
3256ad8b1aafSjsg 		}
3257ad8b1aafSjsg 		break;
3258ad8b1aafSjsg 	default:
3259ad8b1aafSjsg 		dev_err(adev->dev,
3260ad8b1aafSjsg 			"unsupported psp sos firmware\n");
3261ad8b1aafSjsg 		err = -EINVAL;
3262ad8b1aafSjsg 		goto out;
3263ad8b1aafSjsg 	}
3264ad8b1aafSjsg 
3265ad8b1aafSjsg 	return 0;
3266ad8b1aafSjsg out:
3267f005ef32Sjsg 	amdgpu_ucode_release(&adev->psp.sos_fw);
3268ad8b1aafSjsg 
3269ad8b1aafSjsg 	return err;
3270ad8b1aafSjsg }
3271ad8b1aafSjsg 
32725ca02815Sjsg static int parse_ta_bin_descriptor(struct psp_context *psp,
32735ca02815Sjsg 				   const struct psp_fw_bin_desc *desc,
3274ad8b1aafSjsg 				   const struct ta_firmware_header_v2_0 *ta_hdr)
3275ad8b1aafSjsg {
3276ad8b1aafSjsg 	uint8_t *ucode_start_addr  = NULL;
3277ad8b1aafSjsg 
3278ad8b1aafSjsg 	if (!psp || !desc || !ta_hdr)
3279ad8b1aafSjsg 		return -EINVAL;
3280ad8b1aafSjsg 
3281ad8b1aafSjsg 	ucode_start_addr  = (uint8_t *)ta_hdr +
3282ad8b1aafSjsg 			    le32_to_cpu(desc->offset_bytes) +
3283ad8b1aafSjsg 			    le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
3284ad8b1aafSjsg 
3285ad8b1aafSjsg 	switch (desc->fw_type) {
3286ad8b1aafSjsg 	case TA_FW_TYPE_PSP_ASD:
32871bb76ff1Sjsg 		psp->asd_context.bin_desc.fw_version        = le32_to_cpu(desc->fw_version);
32881bb76ff1Sjsg 		psp->asd_context.bin_desc.feature_version   = le32_to_cpu(desc->fw_version);
32891bb76ff1Sjsg 		psp->asd_context.bin_desc.size_bytes        = le32_to_cpu(desc->size_bytes);
32901bb76ff1Sjsg 		psp->asd_context.bin_desc.start_addr        = ucode_start_addr;
3291ad8b1aafSjsg 		break;
3292ad8b1aafSjsg 	case TA_FW_TYPE_PSP_XGMI:
32931bb76ff1Sjsg 		psp->xgmi_context.context.bin_desc.fw_version       = le32_to_cpu(desc->fw_version);
32941bb76ff1Sjsg 		psp->xgmi_context.context.bin_desc.size_bytes       = le32_to_cpu(desc->size_bytes);
32951bb76ff1Sjsg 		psp->xgmi_context.context.bin_desc.start_addr       = ucode_start_addr;
3296ad8b1aafSjsg 		break;
3297ad8b1aafSjsg 	case TA_FW_TYPE_PSP_RAS:
32981bb76ff1Sjsg 		psp->ras_context.context.bin_desc.fw_version        = le32_to_cpu(desc->fw_version);
32991bb76ff1Sjsg 		psp->ras_context.context.bin_desc.size_bytes        = le32_to_cpu(desc->size_bytes);
33001bb76ff1Sjsg 		psp->ras_context.context.bin_desc.start_addr        = ucode_start_addr;
3301ad8b1aafSjsg 		break;
3302ad8b1aafSjsg 	case TA_FW_TYPE_PSP_HDCP:
33031bb76ff1Sjsg 		psp->hdcp_context.context.bin_desc.fw_version       = le32_to_cpu(desc->fw_version);
33041bb76ff1Sjsg 		psp->hdcp_context.context.bin_desc.size_bytes       = le32_to_cpu(desc->size_bytes);
33051bb76ff1Sjsg 		psp->hdcp_context.context.bin_desc.start_addr       = ucode_start_addr;
3306ad8b1aafSjsg 		break;
3307ad8b1aafSjsg 	case TA_FW_TYPE_PSP_DTM:
33081bb76ff1Sjsg 		psp->dtm_context.context.bin_desc.fw_version       = le32_to_cpu(desc->fw_version);
33091bb76ff1Sjsg 		psp->dtm_context.context.bin_desc.size_bytes       = le32_to_cpu(desc->size_bytes);
33101bb76ff1Sjsg 		psp->dtm_context.context.bin_desc.start_addr       = ucode_start_addr;
3311ad8b1aafSjsg 		break;
3312ad8b1aafSjsg 	case TA_FW_TYPE_PSP_RAP:
33131bb76ff1Sjsg 		psp->rap_context.context.bin_desc.fw_version       = le32_to_cpu(desc->fw_version);
33141bb76ff1Sjsg 		psp->rap_context.context.bin_desc.size_bytes       = le32_to_cpu(desc->size_bytes);
33151bb76ff1Sjsg 		psp->rap_context.context.bin_desc.start_addr       = ucode_start_addr;
33165ca02815Sjsg 		break;
33175ca02815Sjsg 	case TA_FW_TYPE_PSP_SECUREDISPLAY:
33181bb76ff1Sjsg 		psp->securedisplay_context.context.bin_desc.fw_version =
33191bb76ff1Sjsg 			le32_to_cpu(desc->fw_version);
33201bb76ff1Sjsg 		psp->securedisplay_context.context.bin_desc.size_bytes =
33211bb76ff1Sjsg 			le32_to_cpu(desc->size_bytes);
33221bb76ff1Sjsg 		psp->securedisplay_context.context.bin_desc.start_addr =
33231bb76ff1Sjsg 			ucode_start_addr;
3324ad8b1aafSjsg 		break;
3325ad8b1aafSjsg 	default:
3326ad8b1aafSjsg 		dev_warn(psp->adev->dev, "Unsupported TA type: %d\n", desc->fw_type);
3327ad8b1aafSjsg 		break;
3328ad8b1aafSjsg 	}
3329ad8b1aafSjsg 
3330ad8b1aafSjsg 	return 0;
3331ad8b1aafSjsg }
3332ad8b1aafSjsg 
3333f005ef32Sjsg static int parse_ta_v1_microcode(struct psp_context *psp)
3334ad8b1aafSjsg {
3335f005ef32Sjsg 	const struct ta_firmware_header_v1_0 *ta_hdr;
3336ad8b1aafSjsg 	struct amdgpu_device *adev = psp->adev;
3337f005ef32Sjsg 
3338f005ef32Sjsg 	ta_hdr = (const struct ta_firmware_header_v1_0 *) adev->psp.ta_fw->data;
3339f005ef32Sjsg 
3340f005ef32Sjsg 	if (le16_to_cpu(ta_hdr->header.header_version_major) != 1)
3341f005ef32Sjsg 		return -EINVAL;
3342f005ef32Sjsg 
3343f005ef32Sjsg 	adev->psp.xgmi_context.context.bin_desc.fw_version =
3344f005ef32Sjsg 		le32_to_cpu(ta_hdr->xgmi.fw_version);
3345f005ef32Sjsg 	adev->psp.xgmi_context.context.bin_desc.size_bytes =
3346f005ef32Sjsg 		le32_to_cpu(ta_hdr->xgmi.size_bytes);
3347f005ef32Sjsg 	adev->psp.xgmi_context.context.bin_desc.start_addr =
3348f005ef32Sjsg 		(uint8_t *)ta_hdr +
3349f005ef32Sjsg 		le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
3350f005ef32Sjsg 
3351f005ef32Sjsg 	adev->psp.ras_context.context.bin_desc.fw_version =
3352f005ef32Sjsg 		le32_to_cpu(ta_hdr->ras.fw_version);
3353f005ef32Sjsg 	adev->psp.ras_context.context.bin_desc.size_bytes =
3354f005ef32Sjsg 		le32_to_cpu(ta_hdr->ras.size_bytes);
3355f005ef32Sjsg 	adev->psp.ras_context.context.bin_desc.start_addr =
3356f005ef32Sjsg 		(uint8_t *)adev->psp.xgmi_context.context.bin_desc.start_addr +
3357f005ef32Sjsg 		le32_to_cpu(ta_hdr->ras.offset_bytes);
3358f005ef32Sjsg 
3359f005ef32Sjsg 	adev->psp.hdcp_context.context.bin_desc.fw_version =
3360f005ef32Sjsg 		le32_to_cpu(ta_hdr->hdcp.fw_version);
3361f005ef32Sjsg 	adev->psp.hdcp_context.context.bin_desc.size_bytes =
3362f005ef32Sjsg 		le32_to_cpu(ta_hdr->hdcp.size_bytes);
3363f005ef32Sjsg 	adev->psp.hdcp_context.context.bin_desc.start_addr =
3364f005ef32Sjsg 		(uint8_t *)ta_hdr +
3365f005ef32Sjsg 		le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
3366f005ef32Sjsg 
3367f005ef32Sjsg 	adev->psp.dtm_context.context.bin_desc.fw_version =
3368f005ef32Sjsg 		le32_to_cpu(ta_hdr->dtm.fw_version);
3369f005ef32Sjsg 	adev->psp.dtm_context.context.bin_desc.size_bytes =
3370f005ef32Sjsg 		le32_to_cpu(ta_hdr->dtm.size_bytes);
3371f005ef32Sjsg 	adev->psp.dtm_context.context.bin_desc.start_addr =
3372f005ef32Sjsg 		(uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
3373f005ef32Sjsg 		le32_to_cpu(ta_hdr->dtm.offset_bytes);
3374f005ef32Sjsg 
3375f005ef32Sjsg 	adev->psp.securedisplay_context.context.bin_desc.fw_version =
3376f005ef32Sjsg 		le32_to_cpu(ta_hdr->securedisplay.fw_version);
3377f005ef32Sjsg 	adev->psp.securedisplay_context.context.bin_desc.size_bytes =
3378f005ef32Sjsg 		le32_to_cpu(ta_hdr->securedisplay.size_bytes);
3379f005ef32Sjsg 	adev->psp.securedisplay_context.context.bin_desc.start_addr =
3380f005ef32Sjsg 		(uint8_t *)adev->psp.hdcp_context.context.bin_desc.start_addr +
3381f005ef32Sjsg 		le32_to_cpu(ta_hdr->securedisplay.offset_bytes);
3382f005ef32Sjsg 
3383f005ef32Sjsg 	adev->psp.ta_fw_version = le32_to_cpu(ta_hdr->header.ucode_version);
3384f005ef32Sjsg 
3385f005ef32Sjsg 	return 0;
3386f005ef32Sjsg }
3387f005ef32Sjsg 
3388f005ef32Sjsg static int parse_ta_v2_microcode(struct psp_context *psp)
3389f005ef32Sjsg {
3390ad8b1aafSjsg 	const struct ta_firmware_header_v2_0 *ta_hdr;
3391f005ef32Sjsg 	struct amdgpu_device *adev = psp->adev;
3392ad8b1aafSjsg 	int err = 0;
3393ad8b1aafSjsg 	int ta_index = 0;
3394ad8b1aafSjsg 
3395ad8b1aafSjsg 	ta_hdr = (const struct ta_firmware_header_v2_0 *)adev->psp.ta_fw->data;
3396ad8b1aafSjsg 
3397f005ef32Sjsg 	if (le16_to_cpu(ta_hdr->header.header_version_major) != 2)
3398f005ef32Sjsg 		return -EINVAL;
3399ad8b1aafSjsg 
34005ca02815Sjsg 	if (le32_to_cpu(ta_hdr->ta_fw_bin_count) >= UCODE_MAX_PSP_PACKAGING) {
3401ad8b1aafSjsg 		dev_err(adev->dev, "packed TA count exceeds maximum limit\n");
3402f005ef32Sjsg 		return -EINVAL;
3403ad8b1aafSjsg 	}
3404ad8b1aafSjsg 
3405ad8b1aafSjsg 	for (ta_index = 0; ta_index < le32_to_cpu(ta_hdr->ta_fw_bin_count); ta_index++) {
3406ad8b1aafSjsg 		err = parse_ta_bin_descriptor(psp,
3407ad8b1aafSjsg 					      &ta_hdr->ta_fw_bin[ta_index],
3408ad8b1aafSjsg 					      ta_hdr);
3409ad8b1aafSjsg 		if (err)
3410ad8b1aafSjsg 			return err;
3411fb4d8502Sjsg 	}
3412fb4d8502Sjsg 
3413f005ef32Sjsg 	return 0;
3414f005ef32Sjsg }
3415f005ef32Sjsg 
3416f005ef32Sjsg int psp_init_ta_microcode(struct psp_context *psp, const char *chip_name)
3417f005ef32Sjsg {
3418f005ef32Sjsg 	const struct common_firmware_header *hdr;
3419f005ef32Sjsg 	struct amdgpu_device *adev = psp->adev;
3420f005ef32Sjsg 	char fw_name[PSP_FW_NAME_LEN];
3421f005ef32Sjsg 	int err;
3422f005ef32Sjsg 
3423f005ef32Sjsg 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
3424f005ef32Sjsg 	err = amdgpu_ucode_request(adev, &adev->psp.ta_fw, fw_name);
3425f005ef32Sjsg 	if (err)
3426f005ef32Sjsg 		return err;
3427f005ef32Sjsg 
3428f005ef32Sjsg 	hdr = (const struct common_firmware_header *)adev->psp.ta_fw->data;
3429f005ef32Sjsg 	switch (le16_to_cpu(hdr->header_version_major)) {
3430f005ef32Sjsg 	case 1:
3431f005ef32Sjsg 		err = parse_ta_v1_microcode(psp);
3432f005ef32Sjsg 		break;
3433f005ef32Sjsg 	case 2:
3434f005ef32Sjsg 		err = parse_ta_v2_microcode(psp);
3435f005ef32Sjsg 		break;
3436f005ef32Sjsg 	default:
3437f005ef32Sjsg 		dev_err(adev->dev, "unsupported TA header version\n");
3438f005ef32Sjsg 		err = -EINVAL;
3439f005ef32Sjsg 	}
3440f005ef32Sjsg 
3441f005ef32Sjsg 	if (err)
3442f005ef32Sjsg 		amdgpu_ucode_release(&adev->psp.ta_fw);
3443f005ef32Sjsg 
3444f005ef32Sjsg 	return err;
3445f005ef32Sjsg }
3446f005ef32Sjsg 
3447f005ef32Sjsg int psp_init_cap_microcode(struct psp_context *psp, const char *chip_name)
34481bb76ff1Sjsg {
34491bb76ff1Sjsg 	struct amdgpu_device *adev = psp->adev;
34501bb76ff1Sjsg 	char fw_name[PSP_FW_NAME_LEN];
34511bb76ff1Sjsg 	const struct psp_firmware_header_v1_0 *cap_hdr_v1_0;
34521bb76ff1Sjsg 	struct amdgpu_firmware_info *info = NULL;
34531bb76ff1Sjsg 	int err = 0;
34541bb76ff1Sjsg 
34551bb76ff1Sjsg 	if (!amdgpu_sriov_vf(adev)) {
34561bb76ff1Sjsg 		dev_err(adev->dev, "cap microcode should only be loaded under SRIOV\n");
34571bb76ff1Sjsg 		return -EINVAL;
34581bb76ff1Sjsg 	}
34591bb76ff1Sjsg 
34601bb76ff1Sjsg 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_cap.bin", chip_name);
3461f005ef32Sjsg 	err = amdgpu_ucode_request(adev, &adev->psp.cap_fw, fw_name);
34621bb76ff1Sjsg 	if (err) {
3463f005ef32Sjsg 		if (err == -ENODEV) {
34641bb76ff1Sjsg 			dev_warn(adev->dev, "cap microcode does not exist, skip\n");
34651bb76ff1Sjsg 			err = 0;
34661bb76ff1Sjsg 			goto out;
34671bb76ff1Sjsg 		}
34681bb76ff1Sjsg 		dev_err(adev->dev, "fail to initialize cap microcode\n");
34691bb76ff1Sjsg 	}
34701bb76ff1Sjsg 
34711bb76ff1Sjsg 	info = &adev->firmware.ucode[AMDGPU_UCODE_ID_CAP];
34721bb76ff1Sjsg 	info->ucode_id = AMDGPU_UCODE_ID_CAP;
34731bb76ff1Sjsg 	info->fw = adev->psp.cap_fw;
34741bb76ff1Sjsg 	cap_hdr_v1_0 = (const struct psp_firmware_header_v1_0 *)
34751bb76ff1Sjsg 		adev->psp.cap_fw->data;
3476f005ef32Sjsg 	adev->firmware.fw_size += ALIGN(
34771bb76ff1Sjsg 			le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes), PAGE_SIZE);
34781bb76ff1Sjsg 	adev->psp.cap_fw_version = le32_to_cpu(cap_hdr_v1_0->header.ucode_version);
34791bb76ff1Sjsg 	adev->psp.cap_feature_version = le32_to_cpu(cap_hdr_v1_0->sos.fw_version);
34801bb76ff1Sjsg 	adev->psp.cap_ucode_size = le32_to_cpu(cap_hdr_v1_0->header.ucode_size_bytes);
34811bb76ff1Sjsg 
34821bb76ff1Sjsg 	return 0;
34831bb76ff1Sjsg 
34841bb76ff1Sjsg out:
3485f005ef32Sjsg 	amdgpu_ucode_release(&adev->psp.cap_fw);
34861bb76ff1Sjsg 	return err;
34871bb76ff1Sjsg }
34881bb76ff1Sjsg 
3489fb4d8502Sjsg static int psp_set_clockgating_state(void *handle,
3490fb4d8502Sjsg 				     enum amd_clockgating_state state)
3491fb4d8502Sjsg {
3492fb4d8502Sjsg 	return 0;
3493fb4d8502Sjsg }
3494fb4d8502Sjsg 
3495fb4d8502Sjsg static int psp_set_powergating_state(void *handle,
3496fb4d8502Sjsg 				     enum amd_powergating_state state)
3497fb4d8502Sjsg {
3498fb4d8502Sjsg 	return 0;
3499fb4d8502Sjsg }
3500fb4d8502Sjsg 
3501c349dbc7Sjsg static ssize_t psp_usbc_pd_fw_sysfs_read(struct device *dev,
3502c349dbc7Sjsg 					 struct device_attribute *attr,
3503c349dbc7Sjsg 					 char *buf)
3504c349dbc7Sjsg {
3505c349dbc7Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
3506ad8b1aafSjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
3507c349dbc7Sjsg 	uint32_t fw_ver;
3508c349dbc7Sjsg 	int ret;
3509c349dbc7Sjsg 
3510c349dbc7Sjsg 	if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) {
3511c349dbc7Sjsg 		DRM_INFO("PSP block is not ready yet.");
3512c349dbc7Sjsg 		return -EBUSY;
3513c349dbc7Sjsg 	}
3514c349dbc7Sjsg 
3515c349dbc7Sjsg 	mutex_lock(&adev->psp.mutex);
3516c349dbc7Sjsg 	ret = psp_read_usbc_pd_fw(&adev->psp, &fw_ver);
3517c349dbc7Sjsg 	mutex_unlock(&adev->psp.mutex);
3518c349dbc7Sjsg 
3519c349dbc7Sjsg 	if (ret) {
3520c349dbc7Sjsg 		DRM_ERROR("Failed to read USBC PD FW, err = %d", ret);
3521c349dbc7Sjsg 		return ret;
3522c349dbc7Sjsg 	}
3523c349dbc7Sjsg 
35245ca02815Sjsg 	return sysfs_emit(buf, "%x\n", fw_ver);
3525c349dbc7Sjsg }
3526c349dbc7Sjsg 
3527c349dbc7Sjsg static ssize_t psp_usbc_pd_fw_sysfs_write(struct device *dev,
3528c349dbc7Sjsg 						       struct device_attribute *attr,
3529c349dbc7Sjsg 						       const char *buf,
3530c349dbc7Sjsg 						       size_t count)
3531c349dbc7Sjsg {
3532c349dbc7Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
3533ad8b1aafSjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
35345ca02815Sjsg 	int ret, idx;
3535c349dbc7Sjsg 	char fw_name[100];
3536c349dbc7Sjsg 	const struct firmware *usbc_pd_fw;
35375ca02815Sjsg 	struct amdgpu_bo *fw_buf_bo = NULL;
35385ca02815Sjsg 	uint64_t fw_pri_mc_addr;
35395ca02815Sjsg 	void *fw_pri_cpu_addr;
3540c349dbc7Sjsg 
3541c349dbc7Sjsg 	if (!adev->ip_blocks[AMD_IP_BLOCK_TYPE_PSP].status.late_initialized) {
3542c349dbc7Sjsg 		DRM_INFO("PSP block is not ready yet.");
3543c349dbc7Sjsg 		return -EBUSY;
3544c349dbc7Sjsg 	}
3545c349dbc7Sjsg 
35465ca02815Sjsg 	if (!drm_dev_enter(ddev, &idx))
35475ca02815Sjsg 		return -ENODEV;
35485ca02815Sjsg 
3549c349dbc7Sjsg 	snprintf(fw_name, sizeof(fw_name), "amdgpu/%s", buf);
3550c349dbc7Sjsg 	ret = request_firmware(&usbc_pd_fw, fw_name, adev->dev);
3551c349dbc7Sjsg 	if (ret)
3552c349dbc7Sjsg 		goto fail;
3553c349dbc7Sjsg 
35545ca02815Sjsg 	/* LFB address which is aligned to 1MB boundary per PSP request */
35555ca02815Sjsg 	ret = amdgpu_bo_create_kernel(adev, usbc_pd_fw->size, 0x100000,
3556f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_VRAM |
3557f005ef32Sjsg 				      AMDGPU_GEM_DOMAIN_GTT,
3558f005ef32Sjsg 				      &fw_buf_bo, &fw_pri_mc_addr,
35595ca02815Sjsg 				      &fw_pri_cpu_addr);
3560c349dbc7Sjsg 	if (ret)
3561c349dbc7Sjsg 		goto rel_buf;
3562c349dbc7Sjsg 
35635ca02815Sjsg 	memcpy_toio(fw_pri_cpu_addr, usbc_pd_fw->data, usbc_pd_fw->size);
3564c349dbc7Sjsg 
3565c349dbc7Sjsg 	mutex_lock(&adev->psp.mutex);
35665ca02815Sjsg 	ret = psp_load_usbc_pd_fw(&adev->psp, fw_pri_mc_addr);
3567c349dbc7Sjsg 	mutex_unlock(&adev->psp.mutex);
3568c349dbc7Sjsg 
35695ca02815Sjsg 	amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
3570c349dbc7Sjsg 
35715ca02815Sjsg rel_buf:
35725ca02815Sjsg 	release_firmware(usbc_pd_fw);
3573c349dbc7Sjsg fail:
3574c349dbc7Sjsg 	if (ret) {
3575c349dbc7Sjsg 		DRM_ERROR("Failed to load USBC PD FW, err = %d", ret);
35765ca02815Sjsg 		count = ret;
3577c349dbc7Sjsg 	}
3578c349dbc7Sjsg 
35795ca02815Sjsg 	drm_dev_exit(idx);
3580c349dbc7Sjsg 	return count;
3581c349dbc7Sjsg }
3582c349dbc7Sjsg 
35835ca02815Sjsg void psp_copy_fw(struct psp_context *psp, uint8_t *start_addr, uint32_t bin_size)
35845ca02815Sjsg {
35855ca02815Sjsg 	int idx;
35865ca02815Sjsg 
35871bb76ff1Sjsg 	if (!drm_dev_enter(adev_to_drm(psp->adev), &idx))
35885ca02815Sjsg 		return;
35895ca02815Sjsg 
35905ca02815Sjsg 	memset(psp->fw_pri_buf, 0, PSP_1_MEG);
35915ca02815Sjsg 	memcpy(psp->fw_pri_buf, start_addr, bin_size);
35925ca02815Sjsg 
35935ca02815Sjsg 	drm_dev_exit(idx);
35945ca02815Sjsg }
35955ca02815Sjsg 
3596f005ef32Sjsg /**
3597f005ef32Sjsg  * DOC: usbc_pd_fw
3598f005ef32Sjsg  * Reading from this file will retrieve the USB-C PD firmware version. Writing to
3599f005ef32Sjsg  * this file will trigger the update process.
3600f005ef32Sjsg  */
3601f005ef32Sjsg static DEVICE_ATTR(usbc_pd_fw, 0644,
3602c349dbc7Sjsg 		   psp_usbc_pd_fw_sysfs_read,
3603c349dbc7Sjsg 		   psp_usbc_pd_fw_sysfs_write);
3604c349dbc7Sjsg 
36055ca02815Sjsg int is_psp_fw_valid(struct psp_bin_desc bin)
36065ca02815Sjsg {
36075ca02815Sjsg 	return bin.size_bytes;
36085ca02815Sjsg }
3609c349dbc7Sjsg 
36101bb76ff1Sjsg static ssize_t amdgpu_psp_vbflash_write(struct file *filp, struct kobject *kobj,
36111bb76ff1Sjsg 					struct bin_attribute *bin_attr,
36121bb76ff1Sjsg 					char *buffer, loff_t pos, size_t count)
36131bb76ff1Sjsg {
36141bb76ff1Sjsg 	STUB();
36151bb76ff1Sjsg 	return -ENOSYS;
36161bb76ff1Sjsg #ifdef notyet
36171bb76ff1Sjsg 	struct device *dev = kobj_to_dev(kobj);
36181bb76ff1Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
36191bb76ff1Sjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
36201bb76ff1Sjsg 
36211bb76ff1Sjsg 	adev->psp.vbflash_done = false;
36221bb76ff1Sjsg 
36231bb76ff1Sjsg 	/* Safeguard against memory drain */
36241bb76ff1Sjsg 	if (adev->psp.vbflash_image_size > AMD_VBIOS_FILE_MAX_SIZE_B) {
36251bb76ff1Sjsg 		dev_err(adev->dev, "File size cannot exceed %u", AMD_VBIOS_FILE_MAX_SIZE_B);
36261bb76ff1Sjsg 		kvfree(adev->psp.vbflash_tmp_buf);
36271bb76ff1Sjsg 		adev->psp.vbflash_tmp_buf = NULL;
36281bb76ff1Sjsg 		adev->psp.vbflash_image_size = 0;
36291bb76ff1Sjsg 		return -ENOMEM;
36301bb76ff1Sjsg 	}
36311bb76ff1Sjsg 
36321bb76ff1Sjsg 	/* TODO Just allocate max for now and optimize to realloc later if needed */
36331bb76ff1Sjsg 	if (!adev->psp.vbflash_tmp_buf) {
36341bb76ff1Sjsg 		adev->psp.vbflash_tmp_buf = kvmalloc(AMD_VBIOS_FILE_MAX_SIZE_B, GFP_KERNEL);
36351bb76ff1Sjsg 		if (!adev->psp.vbflash_tmp_buf)
36361bb76ff1Sjsg 			return -ENOMEM;
36371bb76ff1Sjsg 	}
36381bb76ff1Sjsg 
36391bb76ff1Sjsg 	mutex_lock(&adev->psp.mutex);
36401bb76ff1Sjsg 	memcpy(adev->psp.vbflash_tmp_buf + pos, buffer, count);
36411bb76ff1Sjsg 	adev->psp.vbflash_image_size += count;
36421bb76ff1Sjsg 	mutex_unlock(&adev->psp.mutex);
36431bb76ff1Sjsg 
3644f005ef32Sjsg 	dev_dbg(adev->dev, "IFWI staged for update");
36451bb76ff1Sjsg 
36461bb76ff1Sjsg 	return count;
36471bb76ff1Sjsg #endif
36481bb76ff1Sjsg }
36491bb76ff1Sjsg 
36501bb76ff1Sjsg static ssize_t amdgpu_psp_vbflash_read(struct file *filp, struct kobject *kobj,
36511bb76ff1Sjsg 				       struct bin_attribute *bin_attr, char *buffer,
36521bb76ff1Sjsg 				       loff_t pos, size_t count)
36531bb76ff1Sjsg {
36541bb76ff1Sjsg 	STUB();
36551bb76ff1Sjsg 	return -ENOSYS;
36561bb76ff1Sjsg #ifdef notyet
36571bb76ff1Sjsg 	struct device *dev = kobj_to_dev(kobj);
36581bb76ff1Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
36591bb76ff1Sjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
36601bb76ff1Sjsg 	struct amdgpu_bo *fw_buf_bo = NULL;
36611bb76ff1Sjsg 	uint64_t fw_pri_mc_addr;
36621bb76ff1Sjsg 	void *fw_pri_cpu_addr;
36631bb76ff1Sjsg 	int ret;
36641bb76ff1Sjsg 
3665e60282a8Sjsg 	if (adev->psp.vbflash_image_size == 0)
3666e60282a8Sjsg 		return -EINVAL;
3667e60282a8Sjsg 
3668f005ef32Sjsg 	dev_dbg(adev->dev, "PSP IFWI flash process initiated");
36691bb76ff1Sjsg 
36701bb76ff1Sjsg 	ret = amdgpu_bo_create_kernel(adev, adev->psp.vbflash_image_size,
36711bb76ff1Sjsg 					AMDGPU_GPU_PAGE_SIZE,
36721bb76ff1Sjsg 					AMDGPU_GEM_DOMAIN_VRAM,
36731bb76ff1Sjsg 					&fw_buf_bo,
36741bb76ff1Sjsg 					&fw_pri_mc_addr,
36751bb76ff1Sjsg 					&fw_pri_cpu_addr);
36761bb76ff1Sjsg 	if (ret)
36771bb76ff1Sjsg 		goto rel_buf;
36781bb76ff1Sjsg 
36791bb76ff1Sjsg 	memcpy_toio(fw_pri_cpu_addr, adev->psp.vbflash_tmp_buf, adev->psp.vbflash_image_size);
36801bb76ff1Sjsg 
36811bb76ff1Sjsg 	mutex_lock(&adev->psp.mutex);
36821bb76ff1Sjsg 	ret = psp_update_spirom(&adev->psp, fw_pri_mc_addr);
36831bb76ff1Sjsg 	mutex_unlock(&adev->psp.mutex);
36841bb76ff1Sjsg 
36851bb76ff1Sjsg 	amdgpu_bo_free_kernel(&fw_buf_bo, &fw_pri_mc_addr, &fw_pri_cpu_addr);
36861bb76ff1Sjsg 
36871bb76ff1Sjsg rel_buf:
36881bb76ff1Sjsg 	kvfree(adev->psp.vbflash_tmp_buf);
36891bb76ff1Sjsg 	adev->psp.vbflash_tmp_buf = NULL;
36901bb76ff1Sjsg 	adev->psp.vbflash_image_size = 0;
36911bb76ff1Sjsg 
36921bb76ff1Sjsg 	if (ret) {
3693f005ef32Sjsg 		dev_err(adev->dev, "Failed to load IFWI, err = %d", ret);
36941bb76ff1Sjsg 		return ret;
36951bb76ff1Sjsg 	}
36961bb76ff1Sjsg 
3697f005ef32Sjsg 	dev_dbg(adev->dev, "PSP IFWI flash process done");
36981bb76ff1Sjsg 	return 0;
36991bb76ff1Sjsg #endif
37001bb76ff1Sjsg }
37011bb76ff1Sjsg 
3702f005ef32Sjsg /**
3703f005ef32Sjsg  * DOC: psp_vbflash
3704f005ef32Sjsg  * Writing to this file will stage an IFWI for update. Reading from this file
3705f005ef32Sjsg  * will trigger the update process.
3706f005ef32Sjsg  */
3707f005ef32Sjsg #ifdef notyet
3708f005ef32Sjsg static struct bin_attribute psp_vbflash_bin_attr = {
3709f005ef32Sjsg 	.attr = {.name = "psp_vbflash", .mode = 0660},
3710f005ef32Sjsg 	.size = 0,
3711f005ef32Sjsg 	.write = amdgpu_psp_vbflash_write,
3712f005ef32Sjsg 	.read = amdgpu_psp_vbflash_read,
3713f005ef32Sjsg };
3714f005ef32Sjsg #endif
3715f005ef32Sjsg 
3716f005ef32Sjsg /**
3717f005ef32Sjsg  * DOC: psp_vbflash_status
3718f005ef32Sjsg  * The status of the flash process.
3719f005ef32Sjsg  * 0: IFWI flash not complete.
3720f005ef32Sjsg  * 1: IFWI flash complete.
3721f005ef32Sjsg  */
37221bb76ff1Sjsg static ssize_t amdgpu_psp_vbflash_status(struct device *dev,
37231bb76ff1Sjsg 					 struct device_attribute *attr,
37241bb76ff1Sjsg 					 char *buf)
37251bb76ff1Sjsg {
37261bb76ff1Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
37271bb76ff1Sjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
37281bb76ff1Sjsg 	uint32_t vbflash_status;
37291bb76ff1Sjsg 
37301bb76ff1Sjsg 	vbflash_status = psp_vbflash_status(&adev->psp);
37311bb76ff1Sjsg 	if (!adev->psp.vbflash_done)
37321bb76ff1Sjsg 		vbflash_status = 0;
37331bb76ff1Sjsg 	else if (adev->psp.vbflash_done && !(vbflash_status & 0x80000000))
37341bb76ff1Sjsg 		vbflash_status = 1;
37351bb76ff1Sjsg 
37361bb76ff1Sjsg 	return sysfs_emit(buf, "0x%x\n", vbflash_status);
37371bb76ff1Sjsg }
3738f005ef32Sjsg static DEVICE_ATTR(psp_vbflash_status, 0440, amdgpu_psp_vbflash_status, NULL);
37391bb76ff1Sjsg 
37401bb76ff1Sjsg #ifdef notyet
3741f005ef32Sjsg static struct bin_attribute *bin_flash_attrs[] = {
3742f005ef32Sjsg 	&psp_vbflash_bin_attr,
3743f005ef32Sjsg 	NULL
37441bb76ff1Sjsg };
37451bb76ff1Sjsg #endif
37461bb76ff1Sjsg 
3747f005ef32Sjsg static struct attribute *flash_attrs[] = {
3748f005ef32Sjsg 	&dev_attr_psp_vbflash_status.attr,
3749f005ef32Sjsg 	&dev_attr_usbc_pd_fw.attr,
3750f005ef32Sjsg 	NULL
3751f005ef32Sjsg };
37521bb76ff1Sjsg 
3753f005ef32Sjsg #ifdef notyet
3754f005ef32Sjsg 
3755f005ef32Sjsg static umode_t amdgpu_flash_attr_is_visible(struct kobject *kobj, struct attribute *attr, int idx)
37561bb76ff1Sjsg {
3757f005ef32Sjsg 	struct device *dev = kobj_to_dev(kobj);
3758f005ef32Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
3759f005ef32Sjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
37601bb76ff1Sjsg 
3761f005ef32Sjsg 	if (attr == &dev_attr_usbc_pd_fw.attr)
3762f005ef32Sjsg 		return adev->psp.sup_pd_fw_up ? 0660 : 0;
37631bb76ff1Sjsg 
3764f005ef32Sjsg 	return adev->psp.sup_ifwi_up ? 0440 : 0;
37651bb76ff1Sjsg }
3766f005ef32Sjsg 
3767f005ef32Sjsg static umode_t amdgpu_bin_flash_attr_is_visible(struct kobject *kobj,
3768f005ef32Sjsg 						struct bin_attribute *attr,
3769f005ef32Sjsg 						int idx)
3770f005ef32Sjsg {
3771f005ef32Sjsg 	struct device *dev = kobj_to_dev(kobj);
3772f005ef32Sjsg 	struct drm_device *ddev = dev_get_drvdata(dev);
3773f005ef32Sjsg 	struct amdgpu_device *adev = drm_to_adev(ddev);
3774f005ef32Sjsg 
3775f005ef32Sjsg 	return adev->psp.sup_ifwi_up ? 0660 : 0;
37761bb76ff1Sjsg }
3777f005ef32Sjsg 
3778f005ef32Sjsg const struct attribute_group amdgpu_flash_attr_group = {
3779f005ef32Sjsg 	.attrs = flash_attrs,
3780f005ef32Sjsg 	.bin_attrs = bin_flash_attrs,
3781f005ef32Sjsg 	.is_bin_visible = amdgpu_bin_flash_attr_is_visible,
3782f005ef32Sjsg 	.is_visible = amdgpu_flash_attr_is_visible,
3783f005ef32Sjsg };
3784f005ef32Sjsg 
3785f005ef32Sjsg #endif /* notyet */
37861bb76ff1Sjsg 
3787fb4d8502Sjsg const struct amd_ip_funcs psp_ip_funcs = {
3788fb4d8502Sjsg 	.name = "psp",
3789fb4d8502Sjsg 	.early_init = psp_early_init,
3790fb4d8502Sjsg 	.late_init = NULL,
3791fb4d8502Sjsg 	.sw_init = psp_sw_init,
3792fb4d8502Sjsg 	.sw_fini = psp_sw_fini,
3793fb4d8502Sjsg 	.hw_init = psp_hw_init,
3794fb4d8502Sjsg 	.hw_fini = psp_hw_fini,
3795fb4d8502Sjsg 	.suspend = psp_suspend,
3796fb4d8502Sjsg 	.resume = psp_resume,
3797fb4d8502Sjsg 	.is_idle = NULL,
3798fb4d8502Sjsg 	.check_soft_reset = NULL,
3799fb4d8502Sjsg 	.wait_for_idle = NULL,
3800fb4d8502Sjsg 	.soft_reset = NULL,
3801fb4d8502Sjsg 	.set_clockgating_state = psp_set_clockgating_state,
3802fb4d8502Sjsg 	.set_powergating_state = psp_set_powergating_state,
3803fb4d8502Sjsg };
3804fb4d8502Sjsg 
3805f005ef32Sjsg const struct amdgpu_ip_block_version psp_v3_1_ip_block = {
3806fb4d8502Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
3807fb4d8502Sjsg 	.major = 3,
3808fb4d8502Sjsg 	.minor = 1,
3809fb4d8502Sjsg 	.rev = 0,
3810fb4d8502Sjsg 	.funcs = &psp_ip_funcs,
3811fb4d8502Sjsg };
3812fb4d8502Sjsg 
3813f005ef32Sjsg const struct amdgpu_ip_block_version psp_v10_0_ip_block = {
3814fb4d8502Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
3815fb4d8502Sjsg 	.major = 10,
3816fb4d8502Sjsg 	.minor = 0,
3817fb4d8502Sjsg 	.rev = 0,
3818fb4d8502Sjsg 	.funcs = &psp_ip_funcs,
3819fb4d8502Sjsg };
3820c349dbc7Sjsg 
3821f005ef32Sjsg const struct amdgpu_ip_block_version psp_v11_0_ip_block = {
3822c349dbc7Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
3823c349dbc7Sjsg 	.major = 11,
3824c349dbc7Sjsg 	.minor = 0,
3825c349dbc7Sjsg 	.rev = 0,
3826c349dbc7Sjsg 	.funcs = &psp_ip_funcs,
3827c349dbc7Sjsg };
3828c349dbc7Sjsg 
38295ca02815Sjsg const struct amdgpu_ip_block_version psp_v11_0_8_ip_block = {
38305ca02815Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
38315ca02815Sjsg 	.major = 11,
38325ca02815Sjsg 	.minor = 0,
38335ca02815Sjsg 	.rev = 8,
38345ca02815Sjsg 	.funcs = &psp_ip_funcs,
38355ca02815Sjsg };
38365ca02815Sjsg 
3837f005ef32Sjsg const struct amdgpu_ip_block_version psp_v12_0_ip_block = {
3838c349dbc7Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
3839c349dbc7Sjsg 	.major = 12,
3840c349dbc7Sjsg 	.minor = 0,
3841c349dbc7Sjsg 	.rev = 0,
3842c349dbc7Sjsg 	.funcs = &psp_ip_funcs,
3843c349dbc7Sjsg };
38445ca02815Sjsg 
38455ca02815Sjsg const struct amdgpu_ip_block_version psp_v13_0_ip_block = {
38465ca02815Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
38475ca02815Sjsg 	.major = 13,
38485ca02815Sjsg 	.minor = 0,
38495ca02815Sjsg 	.rev = 0,
38505ca02815Sjsg 	.funcs = &psp_ip_funcs,
38515ca02815Sjsg };
38521bb76ff1Sjsg 
38531bb76ff1Sjsg const struct amdgpu_ip_block_version psp_v13_0_4_ip_block = {
38541bb76ff1Sjsg 	.type = AMD_IP_BLOCK_TYPE_PSP,
38551bb76ff1Sjsg 	.major = 13,
38561bb76ff1Sjsg 	.minor = 0,
38571bb76ff1Sjsg 	.rev = 4,
38581bb76ff1Sjsg 	.funcs = &psp_ip_funcs,
38591bb76ff1Sjsg };
3860