xref: /openbsd-src/sys/dev/pci/drm/amd/amdgpu/amdgpu_cgs.c (revision 093e7a1454e12cc6f937d9b690b75519e2d0b4c1)
1fb4d8502Sjsg /*
2fb4d8502Sjsg  * Copyright 2015 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  *
23fb4d8502Sjsg  */
24fb4d8502Sjsg #include <linux/list.h>
25c349dbc7Sjsg #include <linux/pci.h>
26fb4d8502Sjsg #include <linux/slab.h>
27c349dbc7Sjsg 
28fb4d8502Sjsg #include <linux/firmware.h>
29fb4d8502Sjsg #include <drm/amdgpu_drm.h>
30fb4d8502Sjsg #include "amdgpu.h"
31fb4d8502Sjsg #include "atom.h"
32fb4d8502Sjsg #include "amdgpu_ucode.h"
33fb4d8502Sjsg 
34fb4d8502Sjsg struct amdgpu_cgs_device {
35fb4d8502Sjsg 	struct cgs_device base;
36fb4d8502Sjsg 	struct amdgpu_device *adev;
37fb4d8502Sjsg };
38fb4d8502Sjsg 
39fb4d8502Sjsg #define CGS_FUNC_ADEV							\
40fb4d8502Sjsg 	struct amdgpu_device *adev =					\
41fb4d8502Sjsg 		((struct amdgpu_cgs_device *)cgs_device)->adev
42fb4d8502Sjsg 
43fb4d8502Sjsg 
44f005ef32Sjsg static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned int offset)
45fb4d8502Sjsg {
46fb4d8502Sjsg 	CGS_FUNC_ADEV;
47fb4d8502Sjsg 	return RREG32(offset);
48fb4d8502Sjsg }
49fb4d8502Sjsg 
50f005ef32Sjsg static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned int offset,
51fb4d8502Sjsg 				      uint32_t value)
52fb4d8502Sjsg {
53fb4d8502Sjsg 	CGS_FUNC_ADEV;
54fb4d8502Sjsg 	WREG32(offset, value);
55fb4d8502Sjsg }
56fb4d8502Sjsg 
57fb4d8502Sjsg static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device,
58fb4d8502Sjsg 					     enum cgs_ind_reg space,
59f005ef32Sjsg 					     unsigned int index)
60fb4d8502Sjsg {
61fb4d8502Sjsg 	CGS_FUNC_ADEV;
62fb4d8502Sjsg 	switch (space) {
63fb4d8502Sjsg 	case CGS_IND_REG__PCIE:
64fb4d8502Sjsg 		return RREG32_PCIE(index);
65fb4d8502Sjsg 	case CGS_IND_REG__SMC:
66fb4d8502Sjsg 		return RREG32_SMC(index);
67fb4d8502Sjsg 	case CGS_IND_REG__UVD_CTX:
68fb4d8502Sjsg 		return RREG32_UVD_CTX(index);
69fb4d8502Sjsg 	case CGS_IND_REG__DIDT:
70fb4d8502Sjsg 		return RREG32_DIDT(index);
71fb4d8502Sjsg 	case CGS_IND_REG_GC_CAC:
72fb4d8502Sjsg 		return RREG32_GC_CAC(index);
73fb4d8502Sjsg 	case CGS_IND_REG_SE_CAC:
74fb4d8502Sjsg 		return RREG32_SE_CAC(index);
75fb4d8502Sjsg 	case CGS_IND_REG__AUDIO_ENDPT:
76fb4d8502Sjsg 		DRM_ERROR("audio endpt register access not implemented.\n");
77fb4d8502Sjsg 		return 0;
78ad8b1aafSjsg 	default:
79ad8b1aafSjsg 		BUG();
80fb4d8502Sjsg 	}
81fb4d8502Sjsg 	WARN(1, "Invalid indirect register space");
82fb4d8502Sjsg 	return 0;
83fb4d8502Sjsg }
84fb4d8502Sjsg 
85fb4d8502Sjsg static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
86fb4d8502Sjsg 					  enum cgs_ind_reg space,
87f005ef32Sjsg 					  unsigned int index, uint32_t value)
88fb4d8502Sjsg {
89fb4d8502Sjsg 	CGS_FUNC_ADEV;
90fb4d8502Sjsg 	switch (space) {
91fb4d8502Sjsg 	case CGS_IND_REG__PCIE:
92fb4d8502Sjsg 		return WREG32_PCIE(index, value);
93fb4d8502Sjsg 	case CGS_IND_REG__SMC:
94fb4d8502Sjsg 		return WREG32_SMC(index, value);
95fb4d8502Sjsg 	case CGS_IND_REG__UVD_CTX:
96fb4d8502Sjsg 		return WREG32_UVD_CTX(index, value);
97fb4d8502Sjsg 	case CGS_IND_REG__DIDT:
98fb4d8502Sjsg 		return WREG32_DIDT(index, value);
99fb4d8502Sjsg 	case CGS_IND_REG_GC_CAC:
100fb4d8502Sjsg 		return WREG32_GC_CAC(index, value);
101fb4d8502Sjsg 	case CGS_IND_REG_SE_CAC:
102fb4d8502Sjsg 		return WREG32_SE_CAC(index, value);
103fb4d8502Sjsg 	case CGS_IND_REG__AUDIO_ENDPT:
104fb4d8502Sjsg 		DRM_ERROR("audio endpt register access not implemented.\n");
105fb4d8502Sjsg 		return;
106ad8b1aafSjsg 	default:
107ad8b1aafSjsg 		BUG();
108fb4d8502Sjsg 	}
109fb4d8502Sjsg 	WARN(1, "Invalid indirect register space");
110fb4d8502Sjsg }
111fb4d8502Sjsg 
112fb4d8502Sjsg static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
113fb4d8502Sjsg {
114fb4d8502Sjsg 	CGS_FUNC_ADEV;
115fb4d8502Sjsg 	enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
116fb4d8502Sjsg 
117fb4d8502Sjsg 	switch (fw_type) {
118fb4d8502Sjsg 	case CGS_UCODE_ID_SDMA0:
119fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_SDMA0;
120fb4d8502Sjsg 		break;
121fb4d8502Sjsg 	case CGS_UCODE_ID_SDMA1:
122fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_SDMA1;
123fb4d8502Sjsg 		break;
124fb4d8502Sjsg 	case CGS_UCODE_ID_CP_CE:
125fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_CP_CE;
126fb4d8502Sjsg 		break;
127fb4d8502Sjsg 	case CGS_UCODE_ID_CP_PFP:
128fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_CP_PFP;
129fb4d8502Sjsg 		break;
130fb4d8502Sjsg 	case CGS_UCODE_ID_CP_ME:
131fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_CP_ME;
132fb4d8502Sjsg 		break;
133fb4d8502Sjsg 	case CGS_UCODE_ID_CP_MEC:
134fb4d8502Sjsg 	case CGS_UCODE_ID_CP_MEC_JT1:
135fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_CP_MEC1;
136fb4d8502Sjsg 		break;
137fb4d8502Sjsg 	case CGS_UCODE_ID_CP_MEC_JT2:
138fb4d8502Sjsg 		/* for VI. JT2 should be the same as JT1, because:
139fb4d8502Sjsg 			1, MEC2 and MEC1 use exactly same FW.
140fb4d8502Sjsg 			2, JT2 is not pached but JT1 is.
141fb4d8502Sjsg 		*/
142fb4d8502Sjsg 		if (adev->asic_type >= CHIP_TOPAZ)
143fb4d8502Sjsg 			result = AMDGPU_UCODE_ID_CP_MEC1;
144fb4d8502Sjsg 		else
145fb4d8502Sjsg 			result = AMDGPU_UCODE_ID_CP_MEC2;
146fb4d8502Sjsg 		break;
147fb4d8502Sjsg 	case CGS_UCODE_ID_RLC_G:
148fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_RLC_G;
149fb4d8502Sjsg 		break;
150fb4d8502Sjsg 	case CGS_UCODE_ID_STORAGE:
151fb4d8502Sjsg 		result = AMDGPU_UCODE_ID_STORAGE;
152fb4d8502Sjsg 		break;
153fb4d8502Sjsg 	default:
154fb4d8502Sjsg 		DRM_ERROR("Firmware type not supported\n");
155fb4d8502Sjsg 	}
156fb4d8502Sjsg 	return result;
157fb4d8502Sjsg }
158fb4d8502Sjsg 
159fb4d8502Sjsg static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
160fb4d8502Sjsg 					enum cgs_ucode_id type)
161fb4d8502Sjsg {
162fb4d8502Sjsg 	CGS_FUNC_ADEV;
163fb4d8502Sjsg 	uint16_t fw_version = 0;
164fb4d8502Sjsg 
165fb4d8502Sjsg 	switch (type) {
166fb4d8502Sjsg 	case CGS_UCODE_ID_SDMA0:
167fb4d8502Sjsg 		fw_version = adev->sdma.instance[0].fw_version;
168fb4d8502Sjsg 		break;
169fb4d8502Sjsg 	case CGS_UCODE_ID_SDMA1:
170fb4d8502Sjsg 		fw_version = adev->sdma.instance[1].fw_version;
171fb4d8502Sjsg 		break;
172fb4d8502Sjsg 	case CGS_UCODE_ID_CP_CE:
173fb4d8502Sjsg 		fw_version = adev->gfx.ce_fw_version;
174fb4d8502Sjsg 		break;
175fb4d8502Sjsg 	case CGS_UCODE_ID_CP_PFP:
176fb4d8502Sjsg 		fw_version = adev->gfx.pfp_fw_version;
177fb4d8502Sjsg 		break;
178fb4d8502Sjsg 	case CGS_UCODE_ID_CP_ME:
179fb4d8502Sjsg 		fw_version = adev->gfx.me_fw_version;
180fb4d8502Sjsg 		break;
181fb4d8502Sjsg 	case CGS_UCODE_ID_CP_MEC:
182fb4d8502Sjsg 		fw_version = adev->gfx.mec_fw_version;
183fb4d8502Sjsg 		break;
184fb4d8502Sjsg 	case CGS_UCODE_ID_CP_MEC_JT1:
185fb4d8502Sjsg 		fw_version = adev->gfx.mec_fw_version;
186fb4d8502Sjsg 		break;
187fb4d8502Sjsg 	case CGS_UCODE_ID_CP_MEC_JT2:
188fb4d8502Sjsg 		fw_version = adev->gfx.mec_fw_version;
189fb4d8502Sjsg 		break;
190fb4d8502Sjsg 	case CGS_UCODE_ID_RLC_G:
191fb4d8502Sjsg 		fw_version = adev->gfx.rlc_fw_version;
192fb4d8502Sjsg 		break;
193fb4d8502Sjsg 	case CGS_UCODE_ID_STORAGE:
194fb4d8502Sjsg 		break;
195fb4d8502Sjsg 	default:
196fb4d8502Sjsg 		DRM_ERROR("firmware type %d do not have version\n", type);
197fb4d8502Sjsg 		break;
198fb4d8502Sjsg 	}
199fb4d8502Sjsg 	return fw_version;
200fb4d8502Sjsg }
201fb4d8502Sjsg 
202fb4d8502Sjsg static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
203fb4d8502Sjsg 					enum cgs_ucode_id type,
204fb4d8502Sjsg 					struct cgs_firmware_info *info)
205fb4d8502Sjsg {
206fb4d8502Sjsg 	CGS_FUNC_ADEV;
207fb4d8502Sjsg 
208f005ef32Sjsg 	if (type != CGS_UCODE_ID_SMU && type != CGS_UCODE_ID_SMU_SK) {
209fb4d8502Sjsg 		uint64_t gpu_addr;
210fb4d8502Sjsg 		uint32_t data_size;
211fb4d8502Sjsg 		const struct gfx_firmware_header_v1_0 *header;
212fb4d8502Sjsg 		enum AMDGPU_UCODE_ID id;
213fb4d8502Sjsg 		struct amdgpu_firmware_info *ucode;
214fb4d8502Sjsg 
215fb4d8502Sjsg 		id = fw_type_convert(cgs_device, type);
216*093e7a14Sjsg 		if (id >= AMDGPU_UCODE_ID_MAXIMUM)
217*093e7a14Sjsg 			return -EINVAL;
218*093e7a14Sjsg 
219fb4d8502Sjsg 		ucode = &adev->firmware.ucode[id];
220fb4d8502Sjsg 		if (ucode->fw == NULL)
221fb4d8502Sjsg 			return -EINVAL;
222fb4d8502Sjsg 
223fb4d8502Sjsg 		gpu_addr  = ucode->mc_addr;
224fb4d8502Sjsg 		header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
225fb4d8502Sjsg 		data_size = le32_to_cpu(header->header.ucode_size_bytes);
226fb4d8502Sjsg 
227fb4d8502Sjsg 		if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
228fb4d8502Sjsg 		    (type == CGS_UCODE_ID_CP_MEC_JT2)) {
229f005ef32Sjsg 			gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
230fb4d8502Sjsg 			data_size = le32_to_cpu(header->jt_size) << 2;
231fb4d8502Sjsg 		}
232fb4d8502Sjsg 
233fb4d8502Sjsg 		info->kptr = ucode->kaddr;
234fb4d8502Sjsg 		info->image_size = data_size;
235fb4d8502Sjsg 		info->mc_addr = gpu_addr;
236fb4d8502Sjsg 		info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
237fb4d8502Sjsg 
238f005ef32Sjsg 		if (type == CGS_UCODE_ID_CP_MEC)
239fb4d8502Sjsg 			info->image_size = le32_to_cpu(header->jt_offset) << 2;
240fb4d8502Sjsg 
241fb4d8502Sjsg 		info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
242fb4d8502Sjsg 		info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
243fb4d8502Sjsg 	} else {
244fb4d8502Sjsg 		char fw_name[30] = {0};
245fb4d8502Sjsg 		int err = 0;
246fb4d8502Sjsg 		uint32_t ucode_size;
247fb4d8502Sjsg 		uint32_t ucode_start_address;
248fb4d8502Sjsg 		const uint8_t *src;
249fb4d8502Sjsg 		const struct smc_firmware_header_v1_0 *hdr;
250fb4d8502Sjsg 		const struct common_firmware_header *header;
251fb4d8502Sjsg 		struct amdgpu_firmware_info *ucode = NULL;
252fb4d8502Sjsg 
253fb4d8502Sjsg 		if (!adev->pm.fw) {
254fb4d8502Sjsg 			switch (adev->asic_type) {
255fb4d8502Sjsg 			case CHIP_TAHITI:
256fb4d8502Sjsg 				strlcpy(fw_name, "radeon/tahiti_smc.bin", sizeof(fw_name));
257fb4d8502Sjsg 				break;
258fb4d8502Sjsg 			case CHIP_PITCAIRN:
259fb4d8502Sjsg 				if ((adev->pdev->revision == 0x81) &&
260fb4d8502Sjsg 				    ((adev->pdev->device == 0x6810) ||
261fb4d8502Sjsg 				    (adev->pdev->device == 0x6811))) {
262fb4d8502Sjsg 					info->is_kicker = true;
263fb4d8502Sjsg 					strlcpy(fw_name, "radeon/pitcairn_k_smc.bin", sizeof(fw_name));
264fb4d8502Sjsg 				} else {
265fb4d8502Sjsg 					strlcpy(fw_name, "radeon/pitcairn_smc.bin", sizeof(fw_name));
266fb4d8502Sjsg 				}
267fb4d8502Sjsg 				break;
268fb4d8502Sjsg 			case CHIP_VERDE:
269fb4d8502Sjsg 				if (((adev->pdev->device == 0x6820) &&
270fb4d8502Sjsg 					((adev->pdev->revision == 0x81) ||
271fb4d8502Sjsg 					(adev->pdev->revision == 0x83))) ||
272fb4d8502Sjsg 				    ((adev->pdev->device == 0x6821) &&
273fb4d8502Sjsg 					((adev->pdev->revision == 0x83) ||
274fb4d8502Sjsg 					(adev->pdev->revision == 0x87))) ||
275fb4d8502Sjsg 				    ((adev->pdev->revision == 0x87) &&
276fb4d8502Sjsg 					((adev->pdev->device == 0x6823) ||
277fb4d8502Sjsg 					(adev->pdev->device == 0x682b)))) {
278fb4d8502Sjsg 					info->is_kicker = true;
279fb4d8502Sjsg 					strlcpy(fw_name, "radeon/verde_k_smc.bin", sizeof(fw_name));
280fb4d8502Sjsg 				} else {
281fb4d8502Sjsg 					strlcpy(fw_name, "radeon/verde_smc.bin", sizeof(fw_name));
282fb4d8502Sjsg 				}
283fb4d8502Sjsg 				break;
284fb4d8502Sjsg 			case CHIP_OLAND:
285fb4d8502Sjsg 				if (((adev->pdev->revision == 0x81) &&
286fb4d8502Sjsg 					((adev->pdev->device == 0x6600) ||
287fb4d8502Sjsg 					(adev->pdev->device == 0x6604) ||
288fb4d8502Sjsg 					(adev->pdev->device == 0x6605) ||
289fb4d8502Sjsg 					(adev->pdev->device == 0x6610))) ||
290fb4d8502Sjsg 				    ((adev->pdev->revision == 0x83) &&
291fb4d8502Sjsg 					(adev->pdev->device == 0x6610))) {
292fb4d8502Sjsg 					info->is_kicker = true;
293fb4d8502Sjsg 					strlcpy(fw_name, "radeon/oland_k_smc.bin", sizeof(fw_name));
294fb4d8502Sjsg 				} else {
295fb4d8502Sjsg 					strlcpy(fw_name, "radeon/oland_smc.bin", sizeof(fw_name));
296fb4d8502Sjsg 				}
297fb4d8502Sjsg 				break;
298fb4d8502Sjsg 			case CHIP_HAINAN:
299fb4d8502Sjsg 				if (((adev->pdev->revision == 0x81) &&
300fb4d8502Sjsg 					(adev->pdev->device == 0x6660)) ||
301fb4d8502Sjsg 				    ((adev->pdev->revision == 0x83) &&
302fb4d8502Sjsg 					((adev->pdev->device == 0x6660) ||
303fb4d8502Sjsg 					(adev->pdev->device == 0x6663) ||
304fb4d8502Sjsg 					(adev->pdev->device == 0x6665) ||
305fb4d8502Sjsg 					 (adev->pdev->device == 0x6667)))) {
306fb4d8502Sjsg 					info->is_kicker = true;
307fb4d8502Sjsg 					strlcpy(fw_name, "radeon/hainan_k_smc.bin", sizeof(fw_name));
308fb4d8502Sjsg 				} else if ((adev->pdev->revision == 0xc3) &&
309fb4d8502Sjsg 					 (adev->pdev->device == 0x6665)) {
310fb4d8502Sjsg 					info->is_kicker = true;
311fb4d8502Sjsg 					strlcpy(fw_name, "radeon/banks_k_2_smc.bin", sizeof(fw_name));
312fb4d8502Sjsg 				} else {
313fb4d8502Sjsg 					strlcpy(fw_name, "radeon/hainan_smc.bin", sizeof(fw_name));
314fb4d8502Sjsg 				}
315fb4d8502Sjsg 				break;
316fb4d8502Sjsg 			case CHIP_BONAIRE:
317fb4d8502Sjsg 				if ((adev->pdev->revision == 0x80) ||
318fb4d8502Sjsg 					(adev->pdev->revision == 0x81) ||
319fb4d8502Sjsg 					(adev->pdev->device == 0x665f)) {
320fb4d8502Sjsg 					info->is_kicker = true;
321fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/bonaire_k_smc.bin", sizeof(fw_name));
322fb4d8502Sjsg 				} else {
323fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/bonaire_smc.bin", sizeof(fw_name));
324fb4d8502Sjsg 				}
325fb4d8502Sjsg 				break;
326fb4d8502Sjsg 			case CHIP_HAWAII:
327fb4d8502Sjsg 				if (adev->pdev->revision == 0x80) {
328fb4d8502Sjsg 					info->is_kicker = true;
329fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/hawaii_k_smc.bin", sizeof(fw_name));
330fb4d8502Sjsg 				} else {
331fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/hawaii_smc.bin", sizeof(fw_name));
332fb4d8502Sjsg 				}
333fb4d8502Sjsg 				break;
334fb4d8502Sjsg 			case CHIP_TOPAZ:
335fb4d8502Sjsg 				if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
336fb4d8502Sjsg 				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
337fb4d8502Sjsg 				    ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) ||
338fb4d8502Sjsg 				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
339fb4d8502Sjsg 				    ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
340fb4d8502Sjsg 					info->is_kicker = true;
341fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/topaz_k_smc.bin", sizeof(fw_name));
342fb4d8502Sjsg 				} else
343fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/topaz_smc.bin", sizeof(fw_name));
344fb4d8502Sjsg 				break;
345fb4d8502Sjsg 			case CHIP_TONGA:
346fb4d8502Sjsg 				if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
347fb4d8502Sjsg 				    ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
348fb4d8502Sjsg 					info->is_kicker = true;
349fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/tonga_k_smc.bin", sizeof(fw_name));
350fb4d8502Sjsg 				} else
351fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/tonga_smc.bin", sizeof(fw_name));
352fb4d8502Sjsg 				break;
353fb4d8502Sjsg 			case CHIP_FIJI:
354fb4d8502Sjsg 				strlcpy(fw_name, "amdgpu/fiji_smc.bin", sizeof(fw_name));
355fb4d8502Sjsg 				break;
356fb4d8502Sjsg 			case CHIP_POLARIS11:
357fb4d8502Sjsg 				if (type == CGS_UCODE_ID_SMU) {
3585ca02815Sjsg 					if (ASICID_IS_P21(adev->pdev->device, adev->pdev->revision)) {
359fb4d8502Sjsg 						info->is_kicker = true;
360fb4d8502Sjsg 						strlcpy(fw_name, "amdgpu/polaris11_k_smc.bin", sizeof(fw_name));
3615ca02815Sjsg 					} else if (ASICID_IS_P31(adev->pdev->device, adev->pdev->revision)) {
362fb4d8502Sjsg 						info->is_kicker = true;
363fb4d8502Sjsg 						strlcpy(fw_name, "amdgpu/polaris11_k2_smc.bin", sizeof(fw_name));
364fb4d8502Sjsg 					} else {
365fb4d8502Sjsg 						strlcpy(fw_name, "amdgpu/polaris11_smc.bin", sizeof(fw_name));
366fb4d8502Sjsg 					}
367fb4d8502Sjsg 				} else if (type == CGS_UCODE_ID_SMU_SK) {
368fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/polaris11_smc_sk.bin", sizeof(fw_name));
369fb4d8502Sjsg 				}
370fb4d8502Sjsg 				break;
371fb4d8502Sjsg 			case CHIP_POLARIS10:
372fb4d8502Sjsg 				if (type == CGS_UCODE_ID_SMU) {
3735ca02815Sjsg 					if (ASICID_IS_P20(adev->pdev->device, adev->pdev->revision)) {
374fb4d8502Sjsg 						info->is_kicker = true;
375fb4d8502Sjsg 						strlcpy(fw_name, "amdgpu/polaris10_k_smc.bin", sizeof(fw_name));
3765ca02815Sjsg 					} else if (ASICID_IS_P30(adev->pdev->device, adev->pdev->revision)) {
377fb4d8502Sjsg 						info->is_kicker = true;
378fb4d8502Sjsg 						strlcpy(fw_name, "amdgpu/polaris10_k2_smc.bin", sizeof(fw_name));
379fb4d8502Sjsg 					} else {
380fb4d8502Sjsg 						strlcpy(fw_name, "amdgpu/polaris10_smc.bin", sizeof(fw_name));
381fb4d8502Sjsg 					}
382fb4d8502Sjsg 				} else if (type == CGS_UCODE_ID_SMU_SK) {
383fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/polaris10_smc_sk.bin", sizeof(fw_name));
384fb4d8502Sjsg 				}
385fb4d8502Sjsg 				break;
386fb4d8502Sjsg 			case CHIP_POLARIS12:
3875ca02815Sjsg 				if (ASICID_IS_P23(adev->pdev->device, adev->pdev->revision)) {
388fb4d8502Sjsg 					info->is_kicker = true;
389fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/polaris12_k_smc.bin", sizeof(fw_name));
390fb4d8502Sjsg 				} else {
391fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/polaris12_smc.bin", sizeof(fw_name));
392fb4d8502Sjsg 				}
393fb4d8502Sjsg 				break;
394fb4d8502Sjsg 			case CHIP_VEGAM:
395fb4d8502Sjsg 				strlcpy(fw_name, "amdgpu/vegam_smc.bin", sizeof(fw_name));
396fb4d8502Sjsg 				break;
397fb4d8502Sjsg 			case CHIP_VEGA10:
398fb4d8502Sjsg 				if ((adev->pdev->device == 0x687f) &&
399fb4d8502Sjsg 					((adev->pdev->revision == 0xc0) ||
400fb4d8502Sjsg 					(adev->pdev->revision == 0xc1) ||
401fb4d8502Sjsg 					(adev->pdev->revision == 0xc3)))
402fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/vega10_acg_smc.bin", sizeof(fw_name));
403fb4d8502Sjsg 				else
404fb4d8502Sjsg 					strlcpy(fw_name, "amdgpu/vega10_smc.bin", sizeof(fw_name));
405fb4d8502Sjsg 				break;
406fb4d8502Sjsg 			case CHIP_VEGA12:
407fb4d8502Sjsg 				strlcpy(fw_name, "amdgpu/vega12_smc.bin", sizeof(fw_name));
408fb4d8502Sjsg 				break;
409fb4d8502Sjsg 			case CHIP_VEGA20:
410fb4d8502Sjsg 				strlcpy(fw_name, "amdgpu/vega20_smc.bin", sizeof(fw_name));
411fb4d8502Sjsg 				break;
412fb4d8502Sjsg 			default:
413fb4d8502Sjsg 				DRM_ERROR("SMC firmware not supported\n");
414fb4d8502Sjsg 				return -EINVAL;
415fb4d8502Sjsg 			}
416fb4d8502Sjsg 
417f005ef32Sjsg 			err = amdgpu_ucode_request(adev, &adev->pm.fw, fw_name);
418fb4d8502Sjsg 			if (err) {
419fb4d8502Sjsg 				DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
420f005ef32Sjsg 				amdgpu_ucode_release(&adev->pm.fw);
421fb4d8502Sjsg 				return err;
422fb4d8502Sjsg 			}
423fb4d8502Sjsg 
424fb4d8502Sjsg 			if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
425fb4d8502Sjsg 				ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
426fb4d8502Sjsg 				ucode->ucode_id = AMDGPU_UCODE_ID_SMC;
427fb4d8502Sjsg 				ucode->fw = adev->pm.fw;
428fb4d8502Sjsg 				header = (const struct common_firmware_header *)ucode->fw->data;
429fb4d8502Sjsg 				adev->firmware.fw_size +=
430f005ef32Sjsg 					ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
431fb4d8502Sjsg 			}
432fb4d8502Sjsg 		}
433fb4d8502Sjsg 
434fb4d8502Sjsg 		hdr = (const struct smc_firmware_header_v1_0 *)	adev->pm.fw->data;
435fb4d8502Sjsg 		amdgpu_ucode_print_smc_hdr(&hdr->header);
436fb4d8502Sjsg 		adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
437fb4d8502Sjsg 		ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
438fb4d8502Sjsg 		ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
439fb4d8502Sjsg 		src = (const uint8_t *)(adev->pm.fw->data +
440fb4d8502Sjsg 		       le32_to_cpu(hdr->header.ucode_array_offset_bytes));
441fb4d8502Sjsg 
442fb4d8502Sjsg 		info->version = adev->pm.fw_version;
443fb4d8502Sjsg 		info->image_size = ucode_size;
444fb4d8502Sjsg 		info->ucode_start_address = ucode_start_address;
445fb4d8502Sjsg 		info->kptr = (void *)src;
446fb4d8502Sjsg 	}
447fb4d8502Sjsg 	return 0;
448fb4d8502Sjsg }
449fb4d8502Sjsg 
450fb4d8502Sjsg static const struct cgs_ops amdgpu_cgs_ops = {
451fb4d8502Sjsg 	.read_register = amdgpu_cgs_read_register,
452fb4d8502Sjsg 	.write_register = amdgpu_cgs_write_register,
453fb4d8502Sjsg 	.read_ind_register = amdgpu_cgs_read_ind_register,
454fb4d8502Sjsg 	.write_ind_register = amdgpu_cgs_write_ind_register,
455fb4d8502Sjsg 	.get_firmware_info = amdgpu_cgs_get_firmware_info,
456fb4d8502Sjsg };
457fb4d8502Sjsg 
458fb4d8502Sjsg struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
459fb4d8502Sjsg {
460fb4d8502Sjsg 	struct amdgpu_cgs_device *cgs_device =
461fb4d8502Sjsg 		kmalloc(sizeof(*cgs_device), GFP_KERNEL);
462fb4d8502Sjsg 
463fb4d8502Sjsg 	if (!cgs_device) {
464fb4d8502Sjsg 		DRM_ERROR("Couldn't allocate CGS device structure\n");
465fb4d8502Sjsg 		return NULL;
466fb4d8502Sjsg 	}
467fb4d8502Sjsg 
468fb4d8502Sjsg 	cgs_device->base.ops = &amdgpu_cgs_ops;
469fb4d8502Sjsg 	cgs_device->adev = adev;
470fb4d8502Sjsg 
471fb4d8502Sjsg 	return (struct cgs_device *)cgs_device;
472fb4d8502Sjsg }
473fb4d8502Sjsg 
474fb4d8502Sjsg void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device)
475fb4d8502Sjsg {
476fb4d8502Sjsg 	kfree(cgs_device);
477fb4d8502Sjsg }
478