]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / amd / amdgpu / amdgpu_bios.c
1 /*
2  * Copyright 2008 Advanced Micro Devices, Inc.
3  * Copyright 2008 Red Hat Inc.
4  * Copyright 2009 Jerome Glisse.
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  * Authors: Dave Airlie
25  *          Alex Deucher
26  *          Jerome Glisse
27  */
28
29 #include "amdgpu.h"
30 #include "atom.h"
31
32 #include <linux/device.h>
33 #include <linux/pci.h>
34 #include <linux/slab.h>
35 #include <linux/acpi.h>
36 /*
37  * BIOS.
38  */
39
40 #define AMD_VBIOS_SIGNATURE " 761295520"
41 #define AMD_VBIOS_SIGNATURE_OFFSET 0x30
42 #define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
43 #define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
44 #define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
45 #define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
46
47 /* Check if current bios is an ATOM BIOS.
48  * Return true if it is ATOM BIOS. Otherwise, return false.
49  */
50 static bool check_atom_bios(struct amdgpu_device *adev, size_t size)
51 {
52         uint16_t tmp, bios_header_start;
53         uint8_t *bios = adev->bios;
54
55         if (!bios || size < 0x49) {
56                 dev_dbg(adev->dev, "VBIOS mem is null or mem size is wrong\n");
57                 return false;
58         }
59
60         if (!AMD_IS_VALID_VBIOS(bios)) {
61                 dev_dbg(adev->dev, "VBIOS signature incorrect %x %x\n", bios[0],
62                         bios[1]);
63                 return false;
64         }
65
66         bios_header_start = bios[0x48] | (bios[0x49] << 8);
67         if (!bios_header_start) {
68                 dev_dbg(adev->dev, "Can't locate VBIOS header\n");
69                 return false;
70         }
71
72         tmp = bios_header_start + 4;
73         if (size < tmp) {
74                 dev_dbg(adev->dev, "VBIOS header is broken\n");
75                 return false;
76         }
77
78         if (!memcmp(bios + tmp, "ATOM", 4) ||
79             !memcmp(bios + tmp, "MOTA", 4)) {
80                 dev_dbg(adev->dev, "ATOMBIOS detected\n");
81                 return true;
82         }
83
84         return false;
85 }
86
87 /* If you boot an IGP board with a discrete card as the primary,
88  * the IGP rom is not accessible via the rom bar as the IGP rom is
89  * part of the system bios.  On boot, the system bios puts a
90  * copy of the igp rom at the start of vram if a discrete card is
91  * present.
92  * For SR-IOV, the vbios image is also put in VRAM in the VF.
93  */
94 static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev)
95 {
96         uint8_t __iomem *bios;
97         resource_size_t vram_base;
98         resource_size_t size = 256 * 1024; /* ??? */
99
100         if (!(adev->flags & AMD_IS_APU))
101                 if (amdgpu_device_need_post(adev))
102                         return false;
103
104         /* FB BAR not enabled */
105         if (pci_resource_len(adev->pdev, 0) == 0)
106                 return false;
107
108         adev->bios = NULL;
109         vram_base = pci_resource_start(adev->pdev, 0);
110         bios = ioremap_wc(vram_base, size);
111         if (!bios)
112                 return false;
113
114         adev->bios = kmalloc(size, GFP_KERNEL);
115         if (!adev->bios) {
116                 iounmap(bios);
117                 return false;
118         }
119         adev->bios_size = size;
120         memcpy_fromio(adev->bios, bios, size);
121         iounmap(bios);
122
123         if (!check_atom_bios(adev, size)) {
124                 kfree(adev->bios);
125                 return false;
126         }
127
128         return true;
129 }
130
131 bool amdgpu_read_bios(struct amdgpu_device *adev)
132 {
133         uint8_t __iomem *bios;
134         size_t size;
135
136         adev->bios = NULL;
137         /* XXX: some cards may return 0 for rom size? ddx has a workaround */
138         bios = pci_map_rom(adev->pdev, &size);
139         if (!bios)
140                 return false;
141
142         adev->bios = kzalloc(size, GFP_KERNEL);
143         if (adev->bios == NULL) {
144                 pci_unmap_rom(adev->pdev, bios);
145                 return false;
146         }
147         adev->bios_size = size;
148         memcpy_fromio(adev->bios, bios, size);
149         pci_unmap_rom(adev->pdev, bios);
150
151         if (!check_atom_bios(adev, size)) {
152                 kfree(adev->bios);
153                 return false;
154         }
155
156         return true;
157 }
158
159 static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
160 {
161         u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
162         int len;
163
164         if (!adev->asic_funcs || !adev->asic_funcs->read_bios_from_rom)
165                 return false;
166
167         /* validate VBIOS signature */
168         if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
169                 return false;
170         header[AMD_VBIOS_SIGNATURE_END] = 0;
171
172         if ((!AMD_IS_VALID_VBIOS(header)) ||
173                 memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
174                        AMD_VBIOS_SIGNATURE,
175                        strlen(AMD_VBIOS_SIGNATURE)) != 0)
176                 return false;
177
178         /* valid vbios, go on */
179         len = AMD_VBIOS_LENGTH(header);
180         len = ALIGN(len, 4);
181         adev->bios = kmalloc(len, GFP_KERNEL);
182         if (!adev->bios) {
183                 DRM_ERROR("no memory to allocate for BIOS\n");
184                 return false;
185         }
186         adev->bios_size = len;
187
188         /* read complete BIOS */
189         amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
190
191         if (!check_atom_bios(adev, len)) {
192                 kfree(adev->bios);
193                 return false;
194         }
195
196         return true;
197 }
198
199 static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
200 {
201         phys_addr_t rom = adev->pdev->rom;
202         size_t romlen = adev->pdev->romlen;
203         void __iomem *bios;
204
205         adev->bios = NULL;
206
207         if (!rom || romlen == 0)
208                 return false;
209
210         adev->bios = kzalloc(romlen, GFP_KERNEL);
211         if (!adev->bios)
212                 return false;
213
214         bios = ioremap(rom, romlen);
215         if (!bios)
216                 goto free_bios;
217
218         memcpy_fromio(adev->bios, bios, romlen);
219         iounmap(bios);
220
221         if (!check_atom_bios(adev, romlen))
222                 goto free_bios;
223
224         adev->bios_size = romlen;
225
226         return true;
227 free_bios:
228         kfree(adev->bios);
229         return false;
230 }
231
232 #ifdef CONFIG_ACPI
233 /* ATRM is used to get the BIOS on the discrete cards in
234  * dual-gpu systems.
235  */
236 /* retrieve the ROM in 4k blocks */
237 #define ATRM_BIOS_PAGE 4096
238 /**
239  * amdgpu_atrm_call - fetch a chunk of the vbios
240  *
241  * @atrm_handle: acpi ATRM handle
242  * @bios: vbios image pointer
243  * @offset: offset of vbios image data to fetch
244  * @len: length of vbios image data to fetch
245  *
246  * Executes ATRM to fetch a chunk of the discrete
247  * vbios image on PX systems (all asics).
248  * Returns the length of the buffer fetched.
249  */
250 static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
251                             int offset, int len)
252 {
253         acpi_status status;
254         union acpi_object atrm_arg_elements[2], *obj;
255         struct acpi_object_list atrm_arg;
256         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
257
258         atrm_arg.count = 2;
259         atrm_arg.pointer = &atrm_arg_elements[0];
260
261         atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
262         atrm_arg_elements[0].integer.value = offset;
263
264         atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
265         atrm_arg_elements[1].integer.value = len;
266
267         status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
268         if (ACPI_FAILURE(status)) {
269                 DRM_ERROR("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
270                 return -ENODEV;
271         }
272
273         obj = (union acpi_object *)buffer.pointer;
274         memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
275         len = obj->buffer.length;
276         kfree(buffer.pointer);
277         return len;
278 }
279
280 static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
281 {
282         int ret;
283         int size = 256 * 1024;
284         int i;
285         struct pci_dev *pdev = NULL;
286         acpi_handle dhandle, atrm_handle;
287         acpi_status status;
288         bool found = false;
289
290         /* ATRM is for on-platform devices only */
291         if (dev_is_removable(&adev->pdev->dev))
292                 return false;
293
294         while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {
295                 if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
296                     (pdev->class != PCI_CLASS_DISPLAY_OTHER << 8))
297                         continue;
298
299                 dhandle = ACPI_HANDLE(&pdev->dev);
300                 if (!dhandle)
301                         continue;
302
303                 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
304                 if (ACPI_SUCCESS(status)) {
305                         found = true;
306                         break;
307                 }
308         }
309
310         if (!found)
311                 return false;
312         pci_dev_put(pdev);
313
314         adev->bios = kmalloc(size, GFP_KERNEL);
315         if (!adev->bios) {
316                 dev_err(adev->dev, "Unable to allocate bios\n");
317                 return false;
318         }
319
320         for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
321                 ret = amdgpu_atrm_call(atrm_handle,
322                                        adev->bios,
323                                        (i * ATRM_BIOS_PAGE),
324                                        ATRM_BIOS_PAGE);
325                 if (ret < ATRM_BIOS_PAGE)
326                         break;
327         }
328
329         if (!check_atom_bios(adev, size)) {
330                 kfree(adev->bios);
331                 return false;
332         }
333         adev->bios_size = size;
334         return true;
335 }
336 #else
337 static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
338 {
339         return false;
340 }
341 #endif
342
343 static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
344 {
345         return (!adev->asic_funcs || !adev->asic_funcs->read_disabled_bios) ?
346                 false : amdgpu_asic_read_disabled_bios(adev);
347 }
348
349 #ifdef CONFIG_ACPI
350 static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
351 {
352         struct acpi_table_header *hdr;
353         acpi_size tbl_size;
354         UEFI_ACPI_VFCT *vfct;
355         unsigned int offset;
356
357         if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
358                 return false;
359         tbl_size = hdr->length;
360         if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
361                 dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");
362                 return false;
363         }
364
365         vfct = (UEFI_ACPI_VFCT *)hdr;
366         offset = vfct->VBIOSImageOffset;
367
368         while (offset < tbl_size) {
369                 GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
370                 VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
371
372                 offset += sizeof(VFCT_IMAGE_HEADER);
373                 if (offset > tbl_size) {
374                         dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");
375                         return false;
376                 }
377
378                 offset += vhdr->ImageLength;
379                 if (offset > tbl_size) {
380                         dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");
381                         return false;
382                 }
383
384                 if (vhdr->ImageLength &&
385                     vhdr->PCIBus == adev->pdev->bus->number &&
386                     vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
387                     vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
388                     vhdr->VendorID == adev->pdev->vendor &&
389                     vhdr->DeviceID == adev->pdev->device) {
390                         adev->bios = kmemdup(&vbios->VbiosContent,
391                                              vhdr->ImageLength,
392                                              GFP_KERNEL);
393
394                         if (!check_atom_bios(adev, vhdr->ImageLength)) {
395                                 kfree(adev->bios);
396                                 return false;
397                         }
398                         adev->bios_size = vhdr->ImageLength;
399                         return true;
400                 }
401         }
402
403         dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
404         return false;
405 }
406 #else
407 static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
408 {
409         return false;
410 }
411 #endif
412
413 static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)
414 {
415         if (amdgpu_acpi_vfct_bios(adev)) {
416                 dev_info(adev->dev, "Fetched VBIOS from VFCT\n");
417                 goto success;
418         }
419
420         if (amdgpu_read_bios_from_vram(adev)) {
421                 dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");
422                 goto success;
423         }
424
425         if (amdgpu_read_bios(adev)) {
426                 dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");
427                 goto success;
428         }
429
430         if (amdgpu_read_platform_bios(adev)) {
431                 dev_info(adev->dev, "Fetched VBIOS from platform\n");
432                 goto success;
433         }
434
435         dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
436         return false;
437
438 success:
439         return true;
440 }
441
442 static bool amdgpu_get_bios_dgpu(struct amdgpu_device *adev)
443 {
444         if (amdgpu_atrm_get_bios(adev)) {
445                 dev_info(adev->dev, "Fetched VBIOS from ATRM\n");
446                 goto success;
447         }
448
449         if (amdgpu_acpi_vfct_bios(adev)) {
450                 dev_info(adev->dev, "Fetched VBIOS from VFCT\n");
451                 goto success;
452         }
453
454         /* this is required for SR-IOV */
455         if (amdgpu_read_bios_from_vram(adev)) {
456                 dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");
457                 goto success;
458         }
459
460         if (amdgpu_read_platform_bios(adev)) {
461                 dev_info(adev->dev, "Fetched VBIOS from platform\n");
462                 goto success;
463         }
464
465         if (amdgpu_read_bios(adev)) {
466                 dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");
467                 goto success;
468         }
469
470         if (amdgpu_read_bios_from_rom(adev)) {
471                 dev_info(adev->dev, "Fetched VBIOS from ROM\n");
472                 goto success;
473         }
474
475         if (amdgpu_read_disabled_bios(adev)) {
476                 dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n");
477                 goto success;
478         }
479
480         dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
481         return false;
482
483 success:
484         return true;
485 }
486
487 bool amdgpu_get_bios(struct amdgpu_device *adev)
488 {
489         bool found;
490
491         if (adev->flags & AMD_IS_APU)
492                 found = amdgpu_get_bios_apu(adev);
493         else
494                 found = amdgpu_get_bios_dgpu(adev);
495
496         if (found)
497                 adev->is_atom_fw = adev->asic_type >= CHIP_VEGA10;
498
499         return found;
500 }
501
502 /* helper function for soc15 and onwards to read bios from rom */
503 bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,
504                                      u8 *bios, u32 length_bytes)
505 {
506         u32 *dw_ptr;
507         u32 i, length_dw;
508         u32 rom_offset;
509         u32 rom_index_offset;
510         u32 rom_data_offset;
511
512         if (bios == NULL)
513                 return false;
514         if (length_bytes == 0)
515                 return false;
516         /* APU vbios image is part of sbios image */
517         if (adev->flags & AMD_IS_APU)
518                 return false;
519         if (!adev->smuio.funcs ||
520             !adev->smuio.funcs->get_rom_index_offset ||
521             !adev->smuio.funcs->get_rom_data_offset)
522                 return false;
523
524         dw_ptr = (u32 *)bios;
525         length_dw = ALIGN(length_bytes, 4) / 4;
526
527         rom_index_offset =
528                 adev->smuio.funcs->get_rom_index_offset(adev);
529         rom_data_offset =
530                 adev->smuio.funcs->get_rom_data_offset(adev);
531
532         if (adev->nbio.funcs &&
533             adev->nbio.funcs->get_rom_offset) {
534                 rom_offset = adev->nbio.funcs->get_rom_offset(adev);
535                 rom_offset = rom_offset << 17;
536         } else {
537                 rom_offset = 0;
538         }
539
540         /* set rom index to rom_offset */
541         WREG32(rom_index_offset, rom_offset);
542         /* read out the rom data */
543         for (i = 0; i < length_dw; i++)
544                 dw_ptr[i] = RREG32(rom_data_offset);
545
546         return true;
547 }
This page took 0.060394 seconds and 4 git commands to generate.