blob: 4f973a9c7b8714d55229b6f712522f50fcfb1fdf [file] [log] [blame]
Alex Deucherd38ceaf2015-04-20 16:55:21 -04001/*
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#include <drm/drmP.h>
29#include "amdgpu.h"
30#include "atom.h"
31
Alex Deucherd38ceaf2015-04-20 16:55:21 -040032#include <linux/slab.h>
33#include <linux/acpi.h>
34/*
35 * BIOS.
36 */
37
monk.liuf930b2e2015-10-29 15:33:06 +080038#define AMD_VBIOS_SIGNATURE " 761295520"
39#define AMD_VBIOS_SIGNATURE_OFFSET 0x30
40#define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
41#define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
42#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
43#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
44
Alex Deucherd38ceaf2015-04-20 16:55:21 -040045/* If you boot an IGP board with a discrete card as the primary,
46 * the IGP rom is not accessible via the rom bar as the IGP rom is
47 * part of the system bios. On boot, the system bios puts a
48 * copy of the igp rom at the start of vram if a discrete card is
49 * present.
50 */
51static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
52{
53 uint8_t __iomem *bios;
54 resource_size_t vram_base;
55 resource_size_t size = 256 * 1024; /* ??? */
56
Jammy Zhou2f7d10b2015-07-22 11:29:01 +080057 if (!(adev->flags & AMD_IS_APU))
Alex Deucherd38ceaf2015-04-20 16:55:21 -040058 if (!amdgpu_card_posted(adev))
59 return false;
60
61 adev->bios = NULL;
62 vram_base = pci_resource_start(adev->pdev, 0);
63 bios = ioremap(vram_base, size);
64 if (!bios) {
65 return false;
66 }
67
monk.liuf930b2e2015-10-29 15:33:06 +080068 if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -040069 iounmap(bios);
70 return false;
71 }
72 adev->bios = kmalloc(size, GFP_KERNEL);
Ravikant B Sharma3f123252016-11-08 11:19:42 +053073 if (!adev->bios) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -040074 iounmap(bios);
75 return false;
76 }
Evan Quana9f5db92016-12-07 09:56:46 +080077 adev->bios_size = size;
Alex Deucherd38ceaf2015-04-20 16:55:21 -040078 memcpy_fromio(adev->bios, bios, size);
79 iounmap(bios);
80 return true;
81}
82
83bool amdgpu_read_bios(struct amdgpu_device *adev)
84{
monk.liuf930b2e2015-10-29 15:33:06 +080085 uint8_t __iomem *bios, val[2];
Alex Deucherd38ceaf2015-04-20 16:55:21 -040086 size_t size;
87
88 adev->bios = NULL;
89 /* XXX: some cards may return 0 for rom size? ddx has a workaround */
90 bios = pci_map_rom(adev->pdev, &size);
91 if (!bios) {
92 return false;
93 }
94
monk.liuf930b2e2015-10-29 15:33:06 +080095 val[0] = readb(&bios[0]);
96 val[1] = readb(&bios[1]);
Alex Deucher18da4342015-04-17 10:50:02 -040097
monk.liuf930b2e2015-10-29 15:33:06 +080098 if (size == 0 || !AMD_IS_VALID_VBIOS(val)) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -040099 pci_unmap_rom(adev->pdev, bios);
100 return false;
101 }
Alex Deucher18da4342015-04-17 10:50:02 -0400102 adev->bios = kzalloc(size, GFP_KERNEL);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400103 if (adev->bios == NULL) {
104 pci_unmap_rom(adev->pdev, bios);
105 return false;
106 }
Evan Quana9f5db92016-12-07 09:56:46 +0800107 adev->bios_size = size;
Alex Deucher18da4342015-04-17 10:50:02 -0400108 memcpy_fromio(adev->bios, bios, size);
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400109 pci_unmap_rom(adev->pdev, bios);
110 return true;
111}
112
monk.liuf930b2e2015-10-29 15:33:06 +0800113static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
114{
115 u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
116 int len;
117
118 if (!adev->asic_funcs->read_bios_from_rom)
119 return false;
120
121 /* validate VBIOS signature */
122 if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
123 return false;
124 header[AMD_VBIOS_SIGNATURE_END] = 0;
125
126 if ((!AMD_IS_VALID_VBIOS(header)) ||
127 0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
128 AMD_VBIOS_SIGNATURE,
129 strlen(AMD_VBIOS_SIGNATURE)))
130 return false;
131
132 /* valid vbios, go on */
133 len = AMD_VBIOS_LENGTH(header);
134 len = ALIGN(len, 4);
135 adev->bios = kmalloc(len, GFP_KERNEL);
136 if (!adev->bios) {
137 DRM_ERROR("no memory to allocate for BIOS\n");
138 return false;
139 }
Evan Quana9f5db92016-12-07 09:56:46 +0800140 adev->bios_size = len;
monk.liuf930b2e2015-10-29 15:33:06 +0800141
142 /* read complete BIOS */
143 return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
144}
145
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400146static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
147{
148 uint8_t __iomem *bios;
149 size_t size;
150
151 adev->bios = NULL;
152
153 bios = pci_platform_rom(adev->pdev, &size);
154 if (!bios) {
155 return false;
156 }
157
monk.liuf930b2e2015-10-29 15:33:06 +0800158 if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400159 return false;
160 }
161 adev->bios = kmemdup(bios, size, GFP_KERNEL);
162 if (adev->bios == NULL) {
163 return false;
164 }
Evan Quana9f5db92016-12-07 09:56:46 +0800165 adev->bios_size = size;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400166
167 return true;
168}
169
170#ifdef CONFIG_ACPI
171/* ATRM is used to get the BIOS on the discrete cards in
172 * dual-gpu systems.
173 */
174/* retrieve the ROM in 4k blocks */
175#define ATRM_BIOS_PAGE 4096
176/**
177 * amdgpu_atrm_call - fetch a chunk of the vbios
178 *
179 * @atrm_handle: acpi ATRM handle
180 * @bios: vbios image pointer
181 * @offset: offset of vbios image data to fetch
182 * @len: length of vbios image data to fetch
183 *
184 * Executes ATRM to fetch a chunk of the discrete
185 * vbios image on PX systems (all asics).
186 * Returns the length of the buffer fetched.
187 */
188static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
189 int offset, int len)
190{
191 acpi_status status;
192 union acpi_object atrm_arg_elements[2], *obj;
193 struct acpi_object_list atrm_arg;
194 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
195
196 atrm_arg.count = 2;
197 atrm_arg.pointer = &atrm_arg_elements[0];
198
199 atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
200 atrm_arg_elements[0].integer.value = offset;
201
202 atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
203 atrm_arg_elements[1].integer.value = len;
204
205 status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
206 if (ACPI_FAILURE(status)) {
207 printk("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
208 return -ENODEV;
209 }
210
211 obj = (union acpi_object *)buffer.pointer;
212 memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
213 len = obj->buffer.length;
214 kfree(buffer.pointer);
215 return len;
216}
217
218static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
219{
220 int ret;
221 int size = 256 * 1024;
222 int i;
223 struct pci_dev *pdev = NULL;
224 acpi_handle dhandle, atrm_handle;
225 acpi_status status;
226 bool found = false;
227
228 /* ATRM is for the discrete card only */
Jammy Zhou2f7d10b2015-07-22 11:29:01 +0800229 if (adev->flags & AMD_IS_APU)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400230 return false;
231
232 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
233 dhandle = ACPI_HANDLE(&pdev->dev);
234 if (!dhandle)
235 continue;
236
237 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
238 if (!ACPI_FAILURE(status)) {
239 found = true;
240 break;
241 }
242 }
243
244 if (!found) {
245 while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
246 dhandle = ACPI_HANDLE(&pdev->dev);
247 if (!dhandle)
248 continue;
249
250 status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
251 if (!ACPI_FAILURE(status)) {
252 found = true;
253 break;
254 }
255 }
256 }
257
258 if (!found)
259 return false;
260
261 adev->bios = kmalloc(size, GFP_KERNEL);
262 if (!adev->bios) {
263 DRM_ERROR("Unable to allocate bios\n");
264 return false;
265 }
266
267 for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
268 ret = amdgpu_atrm_call(atrm_handle,
269 adev->bios,
270 (i * ATRM_BIOS_PAGE),
271 ATRM_BIOS_PAGE);
272 if (ret < ATRM_BIOS_PAGE)
273 break;
274 }
275
monk.liuf930b2e2015-10-29 15:33:06 +0800276 if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400277 kfree(adev->bios);
278 return false;
279 }
Evan Quana9f5db92016-12-07 09:56:46 +0800280 adev->bios_size = size;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400281 return true;
282}
283#else
284static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
285{
286 return false;
287}
288#endif
289
290static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
291{
Jammy Zhou2f7d10b2015-07-22 11:29:01 +0800292 if (adev->flags & AMD_IS_APU)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400293 return igp_read_bios_from_vram(adev);
294 else
295 return amdgpu_asic_read_disabled_bios(adev);
296}
297
298#ifdef CONFIG_ACPI
299static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
300{
301 bool ret = false;
302 struct acpi_table_header *hdr;
303 acpi_size tbl_size;
304 UEFI_ACPI_VFCT *vfct;
305 GOP_VBIOS_CONTENT *vbios;
306 VFCT_IMAGE_HEADER *vhdr;
307
308 if (!ACPI_SUCCESS(acpi_get_table_with_size("VFCT", 1, &hdr, &tbl_size)))
309 return false;
310 if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
311 DRM_ERROR("ACPI VFCT table present but broken (too short #1)\n");
312 goto out_unmap;
313 }
314
315 vfct = (UEFI_ACPI_VFCT *)hdr;
316 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) > tbl_size) {
317 DRM_ERROR("ACPI VFCT table present but broken (too short #2)\n");
318 goto out_unmap;
319 }
320
321 vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + vfct->VBIOSImageOffset);
322 vhdr = &vbios->VbiosHeader;
323 DRM_INFO("ACPI VFCT contains a BIOS for %02x:%02x.%d %04x:%04x, size %d\n",
324 vhdr->PCIBus, vhdr->PCIDevice, vhdr->PCIFunction,
325 vhdr->VendorID, vhdr->DeviceID, vhdr->ImageLength);
326
327 if (vhdr->PCIBus != adev->pdev->bus->number ||
328 vhdr->PCIDevice != PCI_SLOT(adev->pdev->devfn) ||
329 vhdr->PCIFunction != PCI_FUNC(adev->pdev->devfn) ||
330 vhdr->VendorID != adev->pdev->vendor ||
331 vhdr->DeviceID != adev->pdev->device) {
332 DRM_INFO("ACPI VFCT table is not for this card\n");
333 goto out_unmap;
334 }
335
336 if (vfct->VBIOSImageOffset + sizeof(VFCT_IMAGE_HEADER) + vhdr->ImageLength > tbl_size) {
337 DRM_ERROR("ACPI VFCT image truncated\n");
338 goto out_unmap;
339 }
340
341 adev->bios = kmemdup(&vbios->VbiosContent, vhdr->ImageLength, GFP_KERNEL);
Evan Quana9f5db92016-12-07 09:56:46 +0800342 adev->bios_size = vhdr->ImageLength;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400343 ret = !!adev->bios;
344
345out_unmap:
346 return ret;
347}
348#else
349static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
350{
351 return false;
352}
353#endif
354
355bool amdgpu_get_bios(struct amdgpu_device *adev)
356{
357 bool r;
Nils Wallménius379548f2016-03-19 16:12:13 +0100358 uint16_t tmp, bios_header_start;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400359
360 r = amdgpu_atrm_get_bios(adev);
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000361 if (!r)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400362 r = amdgpu_acpi_vfct_bios(adev);
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000363 if (!r)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400364 r = igp_read_bios_from_vram(adev);
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000365 if (!r)
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400366 r = amdgpu_read_bios(adev);
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000367 if (!r) {
monk.liuf930b2e2015-10-29 15:33:06 +0800368 r = amdgpu_read_bios_from_rom(adev);
369 }
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000370 if (!r) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400371 r = amdgpu_read_disabled_bios(adev);
372 }
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000373 if (!r) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400374 r = amdgpu_read_platform_bios(adev);
375 }
Edward O'Callaghan004e29c2016-07-12 10:17:53 +1000376 if (!r || adev->bios == NULL) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400377 DRM_ERROR("Unable to locate a BIOS ROM\n");
378 adev->bios = NULL;
379 return false;
380 }
monk.liuf930b2e2015-10-29 15:33:06 +0800381 if (!AMD_IS_VALID_VBIOS(adev->bios)) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400382 printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]);
383 goto free_bios;
384 }
385
386 tmp = RBIOS16(0x18);
387 if (RBIOS8(tmp + 0x14) != 0x0) {
388 DRM_INFO("Not an x86 BIOS ROM, not using.\n");
389 goto free_bios;
390 }
391
Nils Wallménius379548f2016-03-19 16:12:13 +0100392 bios_header_start = RBIOS16(0x48);
393 if (!bios_header_start) {
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400394 goto free_bios;
395 }
Nils Wallménius379548f2016-03-19 16:12:13 +0100396 tmp = bios_header_start + 4;
Alex Deucherd38ceaf2015-04-20 16:55:21 -0400397 if (!memcmp(adev->bios + tmp, "ATOM", 4) ||
398 !memcmp(adev->bios + tmp, "MOTA", 4)) {
399 adev->is_atom_bios = true;
400 } else {
401 adev->is_atom_bios = false;
402 }
403
404 DRM_DEBUG("%sBIOS detected\n", adev->is_atom_bios ? "ATOM" : "COM");
405 return true;
406free_bios:
407 kfree(adev->bios);
408 adev->bios = NULL;
409 return false;
410}