1b843c749SSergey Zigachev /*
2b843c749SSergey Zigachev * Copyright 2015 Advanced Micro Devices, Inc.
3b843c749SSergey Zigachev *
4b843c749SSergey Zigachev * Permission is hereby granted, free of charge, to any person obtaining a
5b843c749SSergey Zigachev * copy of this software and associated documentation files (the "Software"),
6b843c749SSergey Zigachev * to deal in the Software without restriction, including without limitation
7b843c749SSergey Zigachev * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8b843c749SSergey Zigachev * and/or sell copies of the Software, and to permit persons to whom the
9b843c749SSergey Zigachev * Software is furnished to do so, subject to the following conditions:
10b843c749SSergey Zigachev *
11b843c749SSergey Zigachev * The above copyright notice and this permission notice shall be included in
12b843c749SSergey Zigachev * all copies or substantial portions of the Software.
13b843c749SSergey Zigachev *
14b843c749SSergey Zigachev * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b843c749SSergey Zigachev * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b843c749SSergey Zigachev * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17b843c749SSergey Zigachev * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18b843c749SSergey Zigachev * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19b843c749SSergey Zigachev * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20b843c749SSergey Zigachev * OTHER DEALINGS IN THE SOFTWARE.
21b843c749SSergey Zigachev *
22b843c749SSergey Zigachev *
23b843c749SSergey Zigachev */
24b843c749SSergey Zigachev #include <linux/list.h>
25b843c749SSergey Zigachev #include <linux/slab.h>
26b843c749SSergey Zigachev #include <drm/drmP.h>
27b843c749SSergey Zigachev #include <linux/firmware.h>
28b843c749SSergey Zigachev #include <drm/amdgpu_drm.h>
29b843c749SSergey Zigachev #include "amdgpu.h"
30b843c749SSergey Zigachev #include "atom.h"
31b843c749SSergey Zigachev #include "amdgpu_ucode.h"
32b843c749SSergey Zigachev
33b843c749SSergey Zigachev struct amdgpu_cgs_device {
34b843c749SSergey Zigachev struct cgs_device base;
35b843c749SSergey Zigachev struct amdgpu_device *adev;
36b843c749SSergey Zigachev };
37b843c749SSergey Zigachev
38b843c749SSergey Zigachev #define CGS_FUNC_ADEV \
39b843c749SSergey Zigachev struct amdgpu_device *adev = \
40b843c749SSergey Zigachev ((struct amdgpu_cgs_device *)cgs_device)->adev
41b843c749SSergey Zigachev
42b843c749SSergey Zigachev
amdgpu_cgs_read_register(struct cgs_device * cgs_device,unsigned offset)43b843c749SSergey Zigachev static uint32_t amdgpu_cgs_read_register(struct cgs_device *cgs_device, unsigned offset)
44b843c749SSergey Zigachev {
45b843c749SSergey Zigachev CGS_FUNC_ADEV;
46b843c749SSergey Zigachev return RREG32(offset);
47b843c749SSergey Zigachev }
48b843c749SSergey Zigachev
amdgpu_cgs_write_register(struct cgs_device * cgs_device,unsigned offset,uint32_t value)49b843c749SSergey Zigachev static void amdgpu_cgs_write_register(struct cgs_device *cgs_device, unsigned offset,
50b843c749SSergey Zigachev uint32_t value)
51b843c749SSergey Zigachev {
52b843c749SSergey Zigachev CGS_FUNC_ADEV;
53b843c749SSergey Zigachev WREG32(offset, value);
54b843c749SSergey Zigachev }
55b843c749SSergey Zigachev
amdgpu_cgs_read_ind_register(struct cgs_device * cgs_device,enum cgs_ind_reg space,unsigned index)56b843c749SSergey Zigachev static uint32_t amdgpu_cgs_read_ind_register(struct cgs_device *cgs_device,
57b843c749SSergey Zigachev enum cgs_ind_reg space,
58b843c749SSergey Zigachev unsigned index)
59b843c749SSergey Zigachev {
60b843c749SSergey Zigachev CGS_FUNC_ADEV;
61b843c749SSergey Zigachev switch (space) {
62b843c749SSergey Zigachev case CGS_IND_REG__MMIO:
63b843c749SSergey Zigachev return RREG32_IDX(index);
64b843c749SSergey Zigachev case CGS_IND_REG__PCIE:
65b843c749SSergey Zigachev return RREG32_PCIE(index);
66b843c749SSergey Zigachev case CGS_IND_REG__SMC:
67b843c749SSergey Zigachev return RREG32_SMC(index);
68b843c749SSergey Zigachev case CGS_IND_REG__UVD_CTX:
69b843c749SSergey Zigachev return RREG32_UVD_CTX(index);
70b843c749SSergey Zigachev case CGS_IND_REG__DIDT:
71b843c749SSergey Zigachev return RREG32_DIDT(index);
72b843c749SSergey Zigachev case CGS_IND_REG_GC_CAC:
73b843c749SSergey Zigachev return RREG32_GC_CAC(index);
74b843c749SSergey Zigachev case CGS_IND_REG_SE_CAC:
75b843c749SSergey Zigachev return RREG32_SE_CAC(index);
76b843c749SSergey Zigachev case CGS_IND_REG__AUDIO_ENDPT:
77b843c749SSergey Zigachev DRM_ERROR("audio endpt register access not implemented.\n");
78b843c749SSergey Zigachev return 0;
79b843c749SSergey Zigachev }
80b843c749SSergey Zigachev WARN(1, "Invalid indirect register space");
81b843c749SSergey Zigachev return 0;
82b843c749SSergey Zigachev }
83b843c749SSergey Zigachev
amdgpu_cgs_write_ind_register(struct cgs_device * cgs_device,enum cgs_ind_reg space,unsigned index,uint32_t value)84b843c749SSergey Zigachev static void amdgpu_cgs_write_ind_register(struct cgs_device *cgs_device,
85b843c749SSergey Zigachev enum cgs_ind_reg space,
86b843c749SSergey Zigachev unsigned index, uint32_t value)
87b843c749SSergey Zigachev {
88b843c749SSergey Zigachev CGS_FUNC_ADEV;
89b843c749SSergey Zigachev switch (space) {
90b843c749SSergey Zigachev case CGS_IND_REG__MMIO:
91b843c749SSergey Zigachev return WREG32_IDX(index, value);
92b843c749SSergey Zigachev case CGS_IND_REG__PCIE:
93b843c749SSergey Zigachev return WREG32_PCIE(index, value);
94b843c749SSergey Zigachev case CGS_IND_REG__SMC:
95b843c749SSergey Zigachev return WREG32_SMC(index, value);
96b843c749SSergey Zigachev case CGS_IND_REG__UVD_CTX:
97b843c749SSergey Zigachev return WREG32_UVD_CTX(index, value);
98b843c749SSergey Zigachev case CGS_IND_REG__DIDT:
99b843c749SSergey Zigachev return WREG32_DIDT(index, value);
100b843c749SSergey Zigachev case CGS_IND_REG_GC_CAC:
101b843c749SSergey Zigachev return WREG32_GC_CAC(index, value);
102b843c749SSergey Zigachev case CGS_IND_REG_SE_CAC:
103b843c749SSergey Zigachev return WREG32_SE_CAC(index, value);
104b843c749SSergey Zigachev case CGS_IND_REG__AUDIO_ENDPT:
105b843c749SSergey Zigachev DRM_ERROR("audio endpt register access not implemented.\n");
106b843c749SSergey Zigachev return;
107b843c749SSergey Zigachev }
108b843c749SSergey Zigachev WARN(1, "Invalid indirect register space");
109b843c749SSergey Zigachev }
110b843c749SSergey Zigachev
fw_type_convert(struct cgs_device * cgs_device,uint32_t fw_type)111b843c749SSergey Zigachev static uint32_t fw_type_convert(struct cgs_device *cgs_device, uint32_t fw_type)
112b843c749SSergey Zigachev {
113b843c749SSergey Zigachev CGS_FUNC_ADEV;
114b843c749SSergey Zigachev enum AMDGPU_UCODE_ID result = AMDGPU_UCODE_ID_MAXIMUM;
115b843c749SSergey Zigachev
116b843c749SSergey Zigachev switch (fw_type) {
117b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA0:
118b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_SDMA0;
119b843c749SSergey Zigachev break;
120b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA1:
121b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_SDMA1;
122b843c749SSergey Zigachev break;
123b843c749SSergey Zigachev case CGS_UCODE_ID_CP_CE:
124b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_CE;
125b843c749SSergey Zigachev break;
126b843c749SSergey Zigachev case CGS_UCODE_ID_CP_PFP:
127b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_PFP;
128b843c749SSergey Zigachev break;
129b843c749SSergey Zigachev case CGS_UCODE_ID_CP_ME:
130b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_ME;
131b843c749SSergey Zigachev break;
132b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC:
133b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT1:
134b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_MEC1;
135b843c749SSergey Zigachev break;
136b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT2:
137b843c749SSergey Zigachev /* for VI. JT2 should be the same as JT1, because:
138b843c749SSergey Zigachev 1, MEC2 and MEC1 use exactly same FW.
139b843c749SSergey Zigachev 2, JT2 is not pached but JT1 is.
140b843c749SSergey Zigachev */
141b843c749SSergey Zigachev if (adev->asic_type >= CHIP_TOPAZ)
142b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_MEC1;
143b843c749SSergey Zigachev else
144b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_CP_MEC2;
145b843c749SSergey Zigachev break;
146b843c749SSergey Zigachev case CGS_UCODE_ID_RLC_G:
147b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_RLC_G;
148b843c749SSergey Zigachev break;
149b843c749SSergey Zigachev case CGS_UCODE_ID_STORAGE:
150b843c749SSergey Zigachev result = AMDGPU_UCODE_ID_STORAGE;
151b843c749SSergey Zigachev break;
152b843c749SSergey Zigachev default:
153b843c749SSergey Zigachev DRM_ERROR("Firmware type not supported\n");
154b843c749SSergey Zigachev }
155b843c749SSergey Zigachev return result;
156b843c749SSergey Zigachev }
157b843c749SSergey Zigachev
amdgpu_get_firmware_version(struct cgs_device * cgs_device,enum cgs_ucode_id type)158b843c749SSergey Zigachev static uint16_t amdgpu_get_firmware_version(struct cgs_device *cgs_device,
159b843c749SSergey Zigachev enum cgs_ucode_id type)
160b843c749SSergey Zigachev {
161b843c749SSergey Zigachev CGS_FUNC_ADEV;
162b843c749SSergey Zigachev uint16_t fw_version = 0;
163b843c749SSergey Zigachev
164b843c749SSergey Zigachev switch (type) {
165b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA0:
166b843c749SSergey Zigachev fw_version = adev->sdma.instance[0].fw_version;
167b843c749SSergey Zigachev break;
168b843c749SSergey Zigachev case CGS_UCODE_ID_SDMA1:
169b843c749SSergey Zigachev fw_version = adev->sdma.instance[1].fw_version;
170b843c749SSergey Zigachev break;
171b843c749SSergey Zigachev case CGS_UCODE_ID_CP_CE:
172b843c749SSergey Zigachev fw_version = adev->gfx.ce_fw_version;
173b843c749SSergey Zigachev break;
174b843c749SSergey Zigachev case CGS_UCODE_ID_CP_PFP:
175b843c749SSergey Zigachev fw_version = adev->gfx.pfp_fw_version;
176b843c749SSergey Zigachev break;
177b843c749SSergey Zigachev case CGS_UCODE_ID_CP_ME:
178b843c749SSergey Zigachev fw_version = adev->gfx.me_fw_version;
179b843c749SSergey Zigachev break;
180b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC:
181b843c749SSergey Zigachev fw_version = adev->gfx.mec_fw_version;
182b843c749SSergey Zigachev break;
183b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT1:
184b843c749SSergey Zigachev fw_version = adev->gfx.mec_fw_version;
185b843c749SSergey Zigachev break;
186b843c749SSergey Zigachev case CGS_UCODE_ID_CP_MEC_JT2:
187b843c749SSergey Zigachev fw_version = adev->gfx.mec_fw_version;
188b843c749SSergey Zigachev break;
189b843c749SSergey Zigachev case CGS_UCODE_ID_RLC_G:
190b843c749SSergey Zigachev fw_version = adev->gfx.rlc_fw_version;
191b843c749SSergey Zigachev break;
192b843c749SSergey Zigachev case CGS_UCODE_ID_STORAGE:
193b843c749SSergey Zigachev break;
194b843c749SSergey Zigachev default:
195b843c749SSergey Zigachev DRM_ERROR("firmware type %d do not have version\n", type);
196b843c749SSergey Zigachev break;
197b843c749SSergey Zigachev }
198b843c749SSergey Zigachev return fw_version;
199b843c749SSergey Zigachev }
200b843c749SSergey Zigachev
amdgpu_cgs_get_firmware_info(struct cgs_device * cgs_device,enum cgs_ucode_id type,struct cgs_firmware_info * info)201b843c749SSergey Zigachev static int amdgpu_cgs_get_firmware_info(struct cgs_device *cgs_device,
202b843c749SSergey Zigachev enum cgs_ucode_id type,
203b843c749SSergey Zigachev struct cgs_firmware_info *info)
204b843c749SSergey Zigachev {
205b843c749SSergey Zigachev CGS_FUNC_ADEV;
206b843c749SSergey Zigachev
207b843c749SSergey Zigachev if ((CGS_UCODE_ID_SMU != type) && (CGS_UCODE_ID_SMU_SK != type)) {
208b843c749SSergey Zigachev uint64_t gpu_addr;
209b843c749SSergey Zigachev uint32_t data_size;
210b843c749SSergey Zigachev const struct gfx_firmware_header_v1_0 *header;
211b843c749SSergey Zigachev enum AMDGPU_UCODE_ID id;
212b843c749SSergey Zigachev struct amdgpu_firmware_info *ucode;
213b843c749SSergey Zigachev
214b843c749SSergey Zigachev id = fw_type_convert(cgs_device, type);
215b843c749SSergey Zigachev ucode = &adev->firmware.ucode[id];
216b843c749SSergey Zigachev if (ucode->fw == NULL)
217b843c749SSergey Zigachev return -EINVAL;
218b843c749SSergey Zigachev
219b843c749SSergey Zigachev gpu_addr = ucode->mc_addr;
220b843c749SSergey Zigachev header = (const struct gfx_firmware_header_v1_0 *)ucode->fw->data;
221b843c749SSergey Zigachev data_size = le32_to_cpu(header->header.ucode_size_bytes);
222b843c749SSergey Zigachev
223b843c749SSergey Zigachev if ((type == CGS_UCODE_ID_CP_MEC_JT1) ||
224b843c749SSergey Zigachev (type == CGS_UCODE_ID_CP_MEC_JT2)) {
225b843c749SSergey Zigachev gpu_addr += ALIGN(le32_to_cpu(header->header.ucode_size_bytes), PAGE_SIZE);
226b843c749SSergey Zigachev data_size = le32_to_cpu(header->jt_size) << 2;
227b843c749SSergey Zigachev }
228b843c749SSergey Zigachev
229b843c749SSergey Zigachev info->kptr = ucode->kaddr;
230b843c749SSergey Zigachev info->image_size = data_size;
231b843c749SSergey Zigachev info->mc_addr = gpu_addr;
232b843c749SSergey Zigachev info->version = (uint16_t)le32_to_cpu(header->header.ucode_version);
233b843c749SSergey Zigachev
234b843c749SSergey Zigachev if (CGS_UCODE_ID_CP_MEC == type)
235b843c749SSergey Zigachev info->image_size = le32_to_cpu(header->jt_offset) << 2;
236b843c749SSergey Zigachev
237b843c749SSergey Zigachev info->fw_version = amdgpu_get_firmware_version(cgs_device, type);
238b843c749SSergey Zigachev info->feature_version = (uint16_t)le32_to_cpu(header->ucode_feature_version);
239b843c749SSergey Zigachev } else {
240b843c749SSergey Zigachev char fw_name[30] = {0};
241b843c749SSergey Zigachev int err = 0;
242b843c749SSergey Zigachev uint32_t ucode_size;
243b843c749SSergey Zigachev uint32_t ucode_start_address;
244b843c749SSergey Zigachev const uint8_t *src;
245b843c749SSergey Zigachev const struct smc_firmware_header_v1_0 *hdr;
246b843c749SSergey Zigachev const struct common_firmware_header *header;
247b843c749SSergey Zigachev struct amdgpu_firmware_info *ucode = NULL;
248b843c749SSergey Zigachev
249b843c749SSergey Zigachev if (!adev->pm.fw) {
250b843c749SSergey Zigachev switch (adev->asic_type) {
251b843c749SSergey Zigachev case CHIP_TAHITI:
252b843c749SSergey Zigachev strcpy(fw_name, "radeon/tahiti_smc.bin");
253b843c749SSergey Zigachev break;
254b843c749SSergey Zigachev case CHIP_PITCAIRN:
255b843c749SSergey Zigachev if ((adev->pdev->revision == 0x81) &&
256b843c749SSergey Zigachev ((adev->pdev->device == 0x6810) ||
257b843c749SSergey Zigachev (adev->pdev->device == 0x6811))) {
258b843c749SSergey Zigachev info->is_kicker = true;
259b843c749SSergey Zigachev strcpy(fw_name, "radeon/pitcairn_k_smc.bin");
260b843c749SSergey Zigachev } else {
261b843c749SSergey Zigachev strcpy(fw_name, "radeon/pitcairn_smc.bin");
262b843c749SSergey Zigachev }
263b843c749SSergey Zigachev break;
264b843c749SSergey Zigachev case CHIP_VERDE:
265b843c749SSergey Zigachev if (((adev->pdev->device == 0x6820) &&
266b843c749SSergey Zigachev ((adev->pdev->revision == 0x81) ||
267b843c749SSergey Zigachev (adev->pdev->revision == 0x83))) ||
268b843c749SSergey Zigachev ((adev->pdev->device == 0x6821) &&
269b843c749SSergey Zigachev ((adev->pdev->revision == 0x83) ||
270b843c749SSergey Zigachev (adev->pdev->revision == 0x87))) ||
271b843c749SSergey Zigachev ((adev->pdev->revision == 0x87) &&
272b843c749SSergey Zigachev ((adev->pdev->device == 0x6823) ||
273b843c749SSergey Zigachev (adev->pdev->device == 0x682b)))) {
274b843c749SSergey Zigachev info->is_kicker = true;
275b843c749SSergey Zigachev strcpy(fw_name, "radeon/verde_k_smc.bin");
276b843c749SSergey Zigachev } else {
277b843c749SSergey Zigachev strcpy(fw_name, "radeon/verde_smc.bin");
278b843c749SSergey Zigachev }
279b843c749SSergey Zigachev break;
280b843c749SSergey Zigachev case CHIP_OLAND:
281b843c749SSergey Zigachev if (((adev->pdev->revision == 0x81) &&
282b843c749SSergey Zigachev ((adev->pdev->device == 0x6600) ||
283b843c749SSergey Zigachev (adev->pdev->device == 0x6604) ||
284b843c749SSergey Zigachev (adev->pdev->device == 0x6605) ||
285b843c749SSergey Zigachev (adev->pdev->device == 0x6610))) ||
286b843c749SSergey Zigachev ((adev->pdev->revision == 0x83) &&
287b843c749SSergey Zigachev (adev->pdev->device == 0x6610))) {
288b843c749SSergey Zigachev info->is_kicker = true;
289b843c749SSergey Zigachev strcpy(fw_name, "radeon/oland_k_smc.bin");
290b843c749SSergey Zigachev } else {
291b843c749SSergey Zigachev strcpy(fw_name, "radeon/oland_smc.bin");
292b843c749SSergey Zigachev }
293b843c749SSergey Zigachev break;
294b843c749SSergey Zigachev case CHIP_HAINAN:
295b843c749SSergey Zigachev if (((adev->pdev->revision == 0x81) &&
296b843c749SSergey Zigachev (adev->pdev->device == 0x6660)) ||
297b843c749SSergey Zigachev ((adev->pdev->revision == 0x83) &&
298b843c749SSergey Zigachev ((adev->pdev->device == 0x6660) ||
299b843c749SSergey Zigachev (adev->pdev->device == 0x6663) ||
300b843c749SSergey Zigachev (adev->pdev->device == 0x6665) ||
301b843c749SSergey Zigachev (adev->pdev->device == 0x6667)))) {
302b843c749SSergey Zigachev info->is_kicker = true;
303b843c749SSergey Zigachev strcpy(fw_name, "radeon/hainan_k_smc.bin");
304b843c749SSergey Zigachev } else if ((adev->pdev->revision == 0xc3) &&
305b843c749SSergey Zigachev (adev->pdev->device == 0x6665)) {
306b843c749SSergey Zigachev info->is_kicker = true;
307b843c749SSergey Zigachev strcpy(fw_name, "radeon/banks_k_2_smc.bin");
308b843c749SSergey Zigachev } else {
309b843c749SSergey Zigachev strcpy(fw_name, "radeon/hainan_smc.bin");
310b843c749SSergey Zigachev }
311b843c749SSergey Zigachev break;
312b843c749SSergey Zigachev case CHIP_BONAIRE:
313b843c749SSergey Zigachev if ((adev->pdev->revision == 0x80) ||
314b843c749SSergey Zigachev (adev->pdev->revision == 0x81) ||
315b843c749SSergey Zigachev (adev->pdev->device == 0x665f)) {
316b843c749SSergey Zigachev info->is_kicker = true;
317*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_bonaire_k_smc");
318b843c749SSergey Zigachev } else {
319*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_bonaire_smc");
320b843c749SSergey Zigachev }
321b843c749SSergey Zigachev break;
322b843c749SSergey Zigachev case CHIP_HAWAII:
323b843c749SSergey Zigachev if (adev->pdev->revision == 0x80) {
324b843c749SSergey Zigachev info->is_kicker = true;
325*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_hawaii_k_smc");
326b843c749SSergey Zigachev } else {
327*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_hawaii_smc");
328b843c749SSergey Zigachev }
329b843c749SSergey Zigachev break;
330b843c749SSergey Zigachev case CHIP_TOPAZ:
331b843c749SSergey Zigachev if (((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x81)) ||
332b843c749SSergey Zigachev ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0x83)) ||
333b843c749SSergey Zigachev ((adev->pdev->device == 0x6907) && (adev->pdev->revision == 0x87)) ||
334b843c749SSergey Zigachev ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD1)) ||
335b843c749SSergey Zigachev ((adev->pdev->device == 0x6900) && (adev->pdev->revision == 0xD3))) {
336b843c749SSergey Zigachev info->is_kicker = true;
337*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_topaz_k_smc");
338b843c749SSergey Zigachev } else
339*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_topaz_smc");
340b843c749SSergey Zigachev break;
341b843c749SSergey Zigachev case CHIP_TONGA:
342b843c749SSergey Zigachev if (((adev->pdev->device == 0x6939) && (adev->pdev->revision == 0xf1)) ||
343b843c749SSergey Zigachev ((adev->pdev->device == 0x6938) && (adev->pdev->revision == 0xf1))) {
344b843c749SSergey Zigachev info->is_kicker = true;
345*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_tonga_k_smc");
346b843c749SSergey Zigachev } else
347*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_tonga_smc");
348b843c749SSergey Zigachev break;
349b843c749SSergey Zigachev case CHIP_FIJI:
350*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_fiji_smc");
351b843c749SSergey Zigachev break;
352b843c749SSergey Zigachev case CHIP_POLARIS11:
353b843c749SSergey Zigachev if (type == CGS_UCODE_ID_SMU) {
354b843c749SSergey Zigachev if (((adev->pdev->device == 0x67ef) &&
355b843c749SSergey Zigachev ((adev->pdev->revision == 0xe0) ||
356b843c749SSergey Zigachev (adev->pdev->revision == 0xe5))) ||
357b843c749SSergey Zigachev ((adev->pdev->device == 0x67ff) &&
358b843c749SSergey Zigachev ((adev->pdev->revision == 0xcf) ||
359b843c749SSergey Zigachev (adev->pdev->revision == 0xef) ||
360b843c749SSergey Zigachev (adev->pdev->revision == 0xff)))) {
361b843c749SSergey Zigachev info->is_kicker = true;
362*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris11_k_smc");
363b843c749SSergey Zigachev } else if ((adev->pdev->device == 0x67ef) &&
364b843c749SSergey Zigachev (adev->pdev->revision == 0xe2)) {
365b843c749SSergey Zigachev info->is_kicker = true;
366*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris11_k2_smc");
367b843c749SSergey Zigachev } else {
368*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris11_smc");
369b843c749SSergey Zigachev }
370b843c749SSergey Zigachev } else if (type == CGS_UCODE_ID_SMU_SK) {
371*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris11_smc_sk");
372b843c749SSergey Zigachev }
373b843c749SSergey Zigachev break;
374b843c749SSergey Zigachev case CHIP_POLARIS10:
375b843c749SSergey Zigachev if (type == CGS_UCODE_ID_SMU) {
376b843c749SSergey Zigachev if (((adev->pdev->device == 0x67df) &&
377b843c749SSergey Zigachev ((adev->pdev->revision == 0xe0) ||
378b843c749SSergey Zigachev (adev->pdev->revision == 0xe3) ||
379b843c749SSergey Zigachev (adev->pdev->revision == 0xe4) ||
380b843c749SSergey Zigachev (adev->pdev->revision == 0xe5) ||
381b843c749SSergey Zigachev (adev->pdev->revision == 0xe7) ||
382b843c749SSergey Zigachev (adev->pdev->revision == 0xef))) ||
383b843c749SSergey Zigachev ((adev->pdev->device == 0x6fdf) &&
384b843c749SSergey Zigachev ((adev->pdev->revision == 0xef) ||
385b843c749SSergey Zigachev (adev->pdev->revision == 0xff)))) {
386b843c749SSergey Zigachev info->is_kicker = true;
387*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris10_k_smc");
388b843c749SSergey Zigachev } else if ((adev->pdev->device == 0x67df) &&
389b843c749SSergey Zigachev ((adev->pdev->revision == 0xe1) ||
390b843c749SSergey Zigachev (adev->pdev->revision == 0xf7))) {
391b843c749SSergey Zigachev info->is_kicker = true;
392*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris10_k2_smc");
393b843c749SSergey Zigachev } else {
394*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris10_smc");
395b843c749SSergey Zigachev }
396b843c749SSergey Zigachev } else if (type == CGS_UCODE_ID_SMU_SK) {
397*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris10_smc_sk");
398b843c749SSergey Zigachev }
399b843c749SSergey Zigachev break;
400b843c749SSergey Zigachev case CHIP_POLARIS12:
401b843c749SSergey Zigachev if (((adev->pdev->device == 0x6987) &&
402b843c749SSergey Zigachev ((adev->pdev->revision == 0xc0) ||
403b843c749SSergey Zigachev (adev->pdev->revision == 0xc3))) ||
404b843c749SSergey Zigachev ((adev->pdev->device == 0x6981) &&
405b843c749SSergey Zigachev ((adev->pdev->revision == 0x00) ||
406b843c749SSergey Zigachev (adev->pdev->revision == 0x01) ||
407b843c749SSergey Zigachev (adev->pdev->revision == 0x10)))) {
408b843c749SSergey Zigachev info->is_kicker = true;
409*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris12_k_smc");
410b843c749SSergey Zigachev } else {
411*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_polaris12_smc");
412b843c749SSergey Zigachev }
413b843c749SSergey Zigachev break;
414b843c749SSergey Zigachev case CHIP_VEGAM:
415*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_vegam_smc");
416b843c749SSergey Zigachev break;
417b843c749SSergey Zigachev case CHIP_VEGA10:
418b843c749SSergey Zigachev if ((adev->pdev->device == 0x687f) &&
419b843c749SSergey Zigachev ((adev->pdev->revision == 0xc0) ||
420b843c749SSergey Zigachev (adev->pdev->revision == 0xc1) ||
421b843c749SSergey Zigachev (adev->pdev->revision == 0xc3)))
422*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_vega10_acg_smc");
423b843c749SSergey Zigachev else
424*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_vega10_smc");
425b843c749SSergey Zigachev break;
426b843c749SSergey Zigachev case CHIP_VEGA12:
427*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_vega12_smc");
428b843c749SSergey Zigachev break;
429b843c749SSergey Zigachev case CHIP_VEGA20:
430*809f3802SSergey Zigachev strcpy(fw_name, "amdgpufw_vega20_smc");
431b843c749SSergey Zigachev break;
432b843c749SSergey Zigachev default:
433b843c749SSergey Zigachev DRM_ERROR("SMC firmware not supported\n");
434b843c749SSergey Zigachev return -EINVAL;
435b843c749SSergey Zigachev }
436b843c749SSergey Zigachev
437b843c749SSergey Zigachev err = request_firmware(&adev->pm.fw, fw_name, adev->dev);
438b843c749SSergey Zigachev if (err) {
439b843c749SSergey Zigachev DRM_ERROR("Failed to request firmware\n");
440b843c749SSergey Zigachev return err;
441b843c749SSergey Zigachev }
442b843c749SSergey Zigachev
443b843c749SSergey Zigachev err = amdgpu_ucode_validate(adev->pm.fw);
444b843c749SSergey Zigachev if (err) {
445b843c749SSergey Zigachev DRM_ERROR("Failed to load firmware \"%s\"", fw_name);
446b843c749SSergey Zigachev release_firmware(adev->pm.fw);
447b843c749SSergey Zigachev adev->pm.fw = NULL;
448b843c749SSergey Zigachev return err;
449b843c749SSergey Zigachev }
450b843c749SSergey Zigachev
451b843c749SSergey Zigachev if (adev->firmware.load_type == AMDGPU_FW_LOAD_PSP) {
452b843c749SSergey Zigachev ucode = &adev->firmware.ucode[AMDGPU_UCODE_ID_SMC];
453b843c749SSergey Zigachev ucode->ucode_id = AMDGPU_UCODE_ID_SMC;
454b843c749SSergey Zigachev ucode->fw = adev->pm.fw;
455b843c749SSergey Zigachev header = (const struct common_firmware_header *)ucode->fw->data;
456b843c749SSergey Zigachev adev->firmware.fw_size +=
457b843c749SSergey Zigachev ALIGN(le32_to_cpu(header->ucode_size_bytes), PAGE_SIZE);
458b843c749SSergey Zigachev }
459b843c749SSergey Zigachev }
460b843c749SSergey Zigachev
461b843c749SSergey Zigachev hdr = (const struct smc_firmware_header_v1_0 *) adev->pm.fw->data;
462b843c749SSergey Zigachev amdgpu_ucode_print_smc_hdr(&hdr->header);
463b843c749SSergey Zigachev adev->pm.fw_version = le32_to_cpu(hdr->header.ucode_version);
464b843c749SSergey Zigachev ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes);
465b843c749SSergey Zigachev ucode_start_address = le32_to_cpu(hdr->ucode_start_addr);
466b843c749SSergey Zigachev src = (const uint8_t *)(adev->pm.fw->data +
467b843c749SSergey Zigachev le32_to_cpu(hdr->header.ucode_array_offset_bytes));
468b843c749SSergey Zigachev
469b843c749SSergey Zigachev info->version = adev->pm.fw_version;
470b843c749SSergey Zigachev info->image_size = ucode_size;
471b843c749SSergey Zigachev info->ucode_start_address = ucode_start_address;
472b843c749SSergey Zigachev info->kptr = (void *)src;
473b843c749SSergey Zigachev }
474b843c749SSergey Zigachev return 0;
475b843c749SSergey Zigachev }
476b843c749SSergey Zigachev
477b843c749SSergey Zigachev static const struct cgs_ops amdgpu_cgs_ops = {
478b843c749SSergey Zigachev .read_register = amdgpu_cgs_read_register,
479b843c749SSergey Zigachev .write_register = amdgpu_cgs_write_register,
480b843c749SSergey Zigachev .read_ind_register = amdgpu_cgs_read_ind_register,
481b843c749SSergey Zigachev .write_ind_register = amdgpu_cgs_write_ind_register,
482b843c749SSergey Zigachev .get_firmware_info = amdgpu_cgs_get_firmware_info,
483b843c749SSergey Zigachev };
484b843c749SSergey Zigachev
amdgpu_cgs_create_device(struct amdgpu_device * adev)485b843c749SSergey Zigachev struct cgs_device *amdgpu_cgs_create_device(struct amdgpu_device *adev)
486b843c749SSergey Zigachev {
487b843c749SSergey Zigachev struct amdgpu_cgs_device *cgs_device =
48878973132SSergey Zigachev kmalloc(sizeof(*cgs_device), M_DRM, GFP_KERNEL);
489b843c749SSergey Zigachev
490b843c749SSergey Zigachev if (!cgs_device) {
491b843c749SSergey Zigachev DRM_ERROR("Couldn't allocate CGS device structure\n");
492b843c749SSergey Zigachev return NULL;
493b843c749SSergey Zigachev }
494b843c749SSergey Zigachev
495b843c749SSergey Zigachev cgs_device->base.ops = &amdgpu_cgs_ops;
496b843c749SSergey Zigachev cgs_device->adev = adev;
497b843c749SSergey Zigachev
498b843c749SSergey Zigachev return (struct cgs_device *)cgs_device;
499b843c749SSergey Zigachev }
500b843c749SSergey Zigachev
amdgpu_cgs_destroy_device(struct cgs_device * cgs_device)501b843c749SSergey Zigachev void amdgpu_cgs_destroy_device(struct cgs_device *cgs_device)
502b843c749SSergey Zigachev {
503b843c749SSergey Zigachev kfree(cgs_device);
504b843c749SSergey Zigachev }
505