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