1fb4d8502Sjsg /*
2fb4d8502Sjsg * Copyright 2008 Advanced Micro Devices, Inc.
3fb4d8502Sjsg * Copyright 2008 Red Hat Inc.
4fb4d8502Sjsg * Copyright 2009 Jerome Glisse.
5fb4d8502Sjsg *
6fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a
7fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"),
8fb4d8502Sjsg * to deal in the Software without restriction, including without limitation
9fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the
11fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions:
12fb4d8502Sjsg *
13fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in
14fb4d8502Sjsg * all copies or substantial portions of the Software.
15fb4d8502Sjsg *
16fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE.
23fb4d8502Sjsg *
24fb4d8502Sjsg * Authors: Dave Airlie
25fb4d8502Sjsg * Alex Deucher
26fb4d8502Sjsg * Jerome Glisse
27fb4d8502Sjsg */
28c349dbc7Sjsg
29fb4d8502Sjsg #include "amdgpu.h"
30fb4d8502Sjsg #include "atom.h"
31fb4d8502Sjsg
32dfb3bfe4Sjsg #include <linux/device.h>
33c349dbc7Sjsg #include <linux/pci.h>
34fb4d8502Sjsg #include <linux/slab.h>
35fb4d8502Sjsg #include <linux/acpi.h>
36fb4d8502Sjsg
37fb4d8502Sjsg #if defined(__amd64__) || defined(__i386__)
38fb4d8502Sjsg #include <dev/isa/isareg.h>
39fb4d8502Sjsg #include <dev/isa/isavar.h>
40fb4d8502Sjsg #endif
41fb4d8502Sjsg
42fb4d8502Sjsg /*
43fb4d8502Sjsg * BIOS.
44fb4d8502Sjsg */
45fb4d8502Sjsg
46fb4d8502Sjsg #define AMD_VBIOS_SIGNATURE " 761295520"
47fb4d8502Sjsg #define AMD_VBIOS_SIGNATURE_OFFSET 0x30
48fb4d8502Sjsg #define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)
49fb4d8502Sjsg #define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)
50fb4d8502Sjsg #define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)
51fb4d8502Sjsg #define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)
52fb4d8502Sjsg
53fb4d8502Sjsg /* Check if current bios is an ATOM BIOS.
54fb4d8502Sjsg * Return true if it is ATOM BIOS. Otherwise, return false.
55fb4d8502Sjsg */
check_atom_bios(uint8_t * bios,size_t size)56fb4d8502Sjsg static bool check_atom_bios(uint8_t *bios, size_t size)
57fb4d8502Sjsg {
58fb4d8502Sjsg uint16_t tmp, bios_header_start;
59fb4d8502Sjsg
60fb4d8502Sjsg if (!bios || size < 0x49) {
61fb4d8502Sjsg DRM_INFO("vbios mem is null or mem size is wrong\n");
62fb4d8502Sjsg return false;
63fb4d8502Sjsg }
64fb4d8502Sjsg
65fb4d8502Sjsg if (!AMD_IS_VALID_VBIOS(bios)) {
66fb4d8502Sjsg DRM_INFO("BIOS signature incorrect %x %x\n", bios[0], bios[1]);
67fb4d8502Sjsg return false;
68fb4d8502Sjsg }
69fb4d8502Sjsg
70fb4d8502Sjsg bios_header_start = bios[0x48] | (bios[0x49] << 8);
71fb4d8502Sjsg if (!bios_header_start) {
72fb4d8502Sjsg DRM_INFO("Can't locate bios header\n");
73fb4d8502Sjsg return false;
74fb4d8502Sjsg }
75fb4d8502Sjsg
76fb4d8502Sjsg tmp = bios_header_start + 4;
77fb4d8502Sjsg if (size < tmp) {
78fb4d8502Sjsg DRM_INFO("BIOS header is broken\n");
79fb4d8502Sjsg return false;
80fb4d8502Sjsg }
81fb4d8502Sjsg
82fb4d8502Sjsg if (!memcmp(bios + tmp, "ATOM", 4) ||
83fb4d8502Sjsg !memcmp(bios + tmp, "MOTA", 4)) {
84fb4d8502Sjsg DRM_DEBUG("ATOMBIOS detected\n");
85fb4d8502Sjsg return true;
86fb4d8502Sjsg }
87fb4d8502Sjsg
88fb4d8502Sjsg return false;
89fb4d8502Sjsg }
90fb4d8502Sjsg
91fb4d8502Sjsg /* If you boot an IGP board with a discrete card as the primary,
92fb4d8502Sjsg * the IGP rom is not accessible via the rom bar as the IGP rom is
93fb4d8502Sjsg * part of the system bios. On boot, the system bios puts a
94fb4d8502Sjsg * copy of the igp rom at the start of vram if a discrete card is
95fb4d8502Sjsg * present.
96fb4d8502Sjsg */
97fb4d8502Sjsg #ifdef __linux__
igp_read_bios_from_vram(struct amdgpu_device * adev)98fb4d8502Sjsg static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
99fb4d8502Sjsg {
100fb4d8502Sjsg uint8_t __iomem *bios;
101fb4d8502Sjsg resource_size_t vram_base;
102fb4d8502Sjsg resource_size_t size = 256 * 1024; /* ??? */
103fb4d8502Sjsg
104fb4d8502Sjsg if (!(adev->flags & AMD_IS_APU))
105fb4d8502Sjsg if (amdgpu_device_need_post(adev))
106fb4d8502Sjsg return false;
107fb4d8502Sjsg
1085ca02815Sjsg /* FB BAR not enabled */
1095ca02815Sjsg if (pci_resource_len(adev->pdev, 0) == 0)
1105ca02815Sjsg return false;
1115ca02815Sjsg
112fb4d8502Sjsg adev->bios = NULL;
113fb4d8502Sjsg vram_base = pci_resource_start(adev->pdev, 0);
114fb4d8502Sjsg bios = ioremap_wc(vram_base, size);
115*f005ef32Sjsg if (!bios)
116fb4d8502Sjsg return false;
117fb4d8502Sjsg
118fb4d8502Sjsg adev->bios = kmalloc(size, GFP_KERNEL);
119fb4d8502Sjsg if (!adev->bios) {
120fb4d8502Sjsg iounmap(bios);
121fb4d8502Sjsg return false;
122fb4d8502Sjsg }
123fb4d8502Sjsg adev->bios_size = size;
124fb4d8502Sjsg memcpy_fromio(adev->bios, bios, size);
125fb4d8502Sjsg iounmap(bios);
126fb4d8502Sjsg
127fb4d8502Sjsg if (!check_atom_bios(adev->bios, size)) {
128fb4d8502Sjsg kfree(adev->bios);
129fb4d8502Sjsg return false;
130fb4d8502Sjsg }
131fb4d8502Sjsg
132fb4d8502Sjsg return true;
133fb4d8502Sjsg }
134fb4d8502Sjsg #else
igp_read_bios_from_vram(struct amdgpu_device * adev)135fb4d8502Sjsg static bool igp_read_bios_from_vram(struct amdgpu_device *adev)
136fb4d8502Sjsg {
137fb4d8502Sjsg uint8_t __iomem *bios;
138fb4d8502Sjsg resource_size_t size = 256 * 1024; /* ??? */
139fb4d8502Sjsg bus_space_handle_t bsh;
140fb4d8502Sjsg bus_space_tag_t bst = adev->memt;
141fb4d8502Sjsg
142fb4d8502Sjsg if (!(adev->flags & AMD_IS_APU))
143fb4d8502Sjsg if (amdgpu_device_need_post(adev))
144fb4d8502Sjsg return false;
145fb4d8502Sjsg
146fb4d8502Sjsg adev->bios = NULL;
147fb4d8502Sjsg
148fb4d8502Sjsg if (bus_space_map(bst, adev->fb_aper_offset, size, BUS_SPACE_MAP_LINEAR, &bsh) != 0)
149fb4d8502Sjsg return false;
150fb4d8502Sjsg
151fb4d8502Sjsg bios = bus_space_vaddr(adev->memt, bsh);
152fb4d8502Sjsg if (bios == NULL) {
153fb4d8502Sjsg bus_space_unmap(bst, bsh, size);
154fb4d8502Sjsg return false;
155fb4d8502Sjsg }
156fb4d8502Sjsg
157fb4d8502Sjsg adev->bios = kmalloc(size, GFP_KERNEL);
158fb4d8502Sjsg if (!adev->bios) {
159fb4d8502Sjsg bus_space_unmap(bst, bsh, size);
160fb4d8502Sjsg return false;
161fb4d8502Sjsg }
162fb4d8502Sjsg adev->bios_size = size;
163fb4d8502Sjsg memcpy_fromio(adev->bios, bios, size);
164fb4d8502Sjsg bus_space_unmap(bst, bsh, size);
165fb4d8502Sjsg
166fb4d8502Sjsg if (!check_atom_bios(adev->bios, size)) {
167fb4d8502Sjsg kfree(adev->bios);
168fb4d8502Sjsg return false;
169fb4d8502Sjsg }
170fb4d8502Sjsg
171fb4d8502Sjsg return true;
172fb4d8502Sjsg }
173fb4d8502Sjsg #endif
174fb4d8502Sjsg
175fb4d8502Sjsg #ifdef __linux__
amdgpu_read_bios(struct amdgpu_device * adev)176fb4d8502Sjsg bool amdgpu_read_bios(struct amdgpu_device *adev)
177fb4d8502Sjsg {
178fb4d8502Sjsg uint8_t __iomem *bios;
179fb4d8502Sjsg size_t size;
180fb4d8502Sjsg
181fb4d8502Sjsg adev->bios = NULL;
182fb4d8502Sjsg /* XXX: some cards may return 0 for rom size? ddx has a workaround */
183fb4d8502Sjsg bios = pci_map_rom(adev->pdev, &size);
184*f005ef32Sjsg if (!bios)
185fb4d8502Sjsg return false;
186fb4d8502Sjsg
187fb4d8502Sjsg adev->bios = kzalloc(size, GFP_KERNEL);
188fb4d8502Sjsg if (adev->bios == NULL) {
189fb4d8502Sjsg pci_unmap_rom(adev->pdev, bios);
190fb4d8502Sjsg return false;
191fb4d8502Sjsg }
192fb4d8502Sjsg adev->bios_size = size;
193fb4d8502Sjsg memcpy_fromio(adev->bios, bios, size);
194fb4d8502Sjsg pci_unmap_rom(adev->pdev, bios);
195fb4d8502Sjsg
196fb4d8502Sjsg if (!check_atom_bios(adev->bios, size)) {
197fb4d8502Sjsg kfree(adev->bios);
198fb4d8502Sjsg return false;
199fb4d8502Sjsg }
200fb4d8502Sjsg
201fb4d8502Sjsg return true;
202fb4d8502Sjsg }
203fb4d8502Sjsg #else
amdgpu_read_bios(struct amdgpu_device * adev)204fb4d8502Sjsg bool amdgpu_read_bios(struct amdgpu_device *adev)
205fb4d8502Sjsg {
206fb4d8502Sjsg size_t size;
207fb4d8502Sjsg pcireg_t address, mask;
208fb4d8502Sjsg bus_space_handle_t romh;
209fb4d8502Sjsg int rc;
210fb4d8502Sjsg
211fb4d8502Sjsg adev->bios = NULL;
212fb4d8502Sjsg /* XXX: some cards may return 0 for rom size? ddx has a workaround */
213fb4d8502Sjsg
214fb4d8502Sjsg address = pci_conf_read(adev->pc, adev->pa_tag, PCI_ROM_REG);
215fb4d8502Sjsg pci_conf_write(adev->pc, adev->pa_tag, PCI_ROM_REG, ~PCI_ROM_ENABLE);
216fb4d8502Sjsg mask = pci_conf_read(adev->pc, adev->pa_tag, PCI_ROM_REG);
217fb4d8502Sjsg address |= PCI_ROM_ENABLE;
218fb4d8502Sjsg pci_conf_write(adev->pc, adev->pa_tag, PCI_ROM_REG, address);
219fb4d8502Sjsg
220fb4d8502Sjsg size = PCI_ROM_SIZE(mask);
221fb4d8502Sjsg if (size == 0)
222fb4d8502Sjsg return false;
223ce0b60d5Sjsg rc = bus_space_map(adev->memt, PCI_ROM_ADDR(address), size, 0, &romh);
224fb4d8502Sjsg if (rc != 0) {
225fb4d8502Sjsg printf(": can't map PCI ROM (%d)\n", rc);
226fb4d8502Sjsg return false;
227fb4d8502Sjsg }
228fb4d8502Sjsg
229fb4d8502Sjsg adev->bios = kzalloc(size, GFP_KERNEL);
230fb4d8502Sjsg adev->bios_size = size;
231ce0b60d5Sjsg bus_space_read_region_1(adev->memt, romh, 0, adev->bios, size);
232fb4d8502Sjsg bus_space_unmap(adev->memt, romh, size);
233fb4d8502Sjsg
234fb4d8502Sjsg if (!check_atom_bios(adev->bios, size)) {
235fb4d8502Sjsg kfree(adev->bios);
236fb4d8502Sjsg return false;
237fb4d8502Sjsg }
238fb4d8502Sjsg
239fb4d8502Sjsg return true;
240fb4d8502Sjsg }
241fb4d8502Sjsg #endif
242fb4d8502Sjsg
amdgpu_read_bios_from_rom(struct amdgpu_device * adev)243fb4d8502Sjsg static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)
244fb4d8502Sjsg {
245fb4d8502Sjsg u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};
246fb4d8502Sjsg int len;
247fb4d8502Sjsg
2485ca02815Sjsg if (!adev->asic_funcs || !adev->asic_funcs->read_bios_from_rom)
249fb4d8502Sjsg return false;
250fb4d8502Sjsg
251fb4d8502Sjsg /* validate VBIOS signature */
252fb4d8502Sjsg if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)
253fb4d8502Sjsg return false;
254fb4d8502Sjsg header[AMD_VBIOS_SIGNATURE_END] = 0;
255fb4d8502Sjsg
256fb4d8502Sjsg if ((!AMD_IS_VALID_VBIOS(header)) ||
257*f005ef32Sjsg memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
258fb4d8502Sjsg AMD_VBIOS_SIGNATURE,
259*f005ef32Sjsg strlen(AMD_VBIOS_SIGNATURE)) != 0)
260fb4d8502Sjsg return false;
261fb4d8502Sjsg
262fb4d8502Sjsg /* valid vbios, go on */
263fb4d8502Sjsg len = AMD_VBIOS_LENGTH(header);
264*f005ef32Sjsg len = ALIGN(len, 4);
265fb4d8502Sjsg adev->bios = kmalloc(len, GFP_KERNEL);
266fb4d8502Sjsg if (!adev->bios) {
267fb4d8502Sjsg DRM_ERROR("no memory to allocate for BIOS\n");
268fb4d8502Sjsg return false;
269fb4d8502Sjsg }
270fb4d8502Sjsg adev->bios_size = len;
271fb4d8502Sjsg
272fb4d8502Sjsg /* read complete BIOS */
273fb4d8502Sjsg amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);
274fb4d8502Sjsg
275fb4d8502Sjsg if (!check_atom_bios(adev->bios, len)) {
276fb4d8502Sjsg kfree(adev->bios);
277fb4d8502Sjsg return false;
278fb4d8502Sjsg }
279fb4d8502Sjsg
280fb4d8502Sjsg return true;
281fb4d8502Sjsg }
282fb4d8502Sjsg
283fb4d8502Sjsg #ifdef __linux__
amdgpu_read_platform_bios(struct amdgpu_device * adev)284fb4d8502Sjsg static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
285fb4d8502Sjsg {
286c349dbc7Sjsg phys_addr_t rom = adev->pdev->rom;
287c349dbc7Sjsg size_t romlen = adev->pdev->romlen;
288c349dbc7Sjsg void __iomem *bios;
289fb4d8502Sjsg
290fb4d8502Sjsg adev->bios = NULL;
291fb4d8502Sjsg
292c349dbc7Sjsg if (!rom || romlen == 0)
293fb4d8502Sjsg return false;
294fb4d8502Sjsg
295c349dbc7Sjsg adev->bios = kzalloc(romlen, GFP_KERNEL);
296c349dbc7Sjsg if (!adev->bios)
297fb4d8502Sjsg return false;
298fb4d8502Sjsg
299c349dbc7Sjsg bios = ioremap(rom, romlen);
300c349dbc7Sjsg if (!bios)
301c349dbc7Sjsg goto free_bios;
302c349dbc7Sjsg
303c349dbc7Sjsg memcpy_fromio(adev->bios, bios, romlen);
304c349dbc7Sjsg iounmap(bios);
305c349dbc7Sjsg
306c349dbc7Sjsg if (!check_atom_bios(adev->bios, romlen))
307c349dbc7Sjsg goto free_bios;
308c349dbc7Sjsg
309c349dbc7Sjsg adev->bios_size = romlen;
310fb4d8502Sjsg
311fb4d8502Sjsg return true;
312c349dbc7Sjsg free_bios:
313c349dbc7Sjsg kfree(adev->bios);
314c349dbc7Sjsg return false;
315fb4d8502Sjsg }
316fb4d8502Sjsg #else
amdgpu_read_platform_bios(struct amdgpu_device * adev)317fb4d8502Sjsg static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)
318fb4d8502Sjsg {
319fb4d8502Sjsg #if defined(__amd64__) || defined(__i386__)
320fb4d8502Sjsg uint8_t __iomem *bios;
321fb4d8502Sjsg bus_size_t size = 256 * 1024; /* ??? */
322fb4d8502Sjsg
323fb4d8502Sjsg adev->bios = NULL;
324fb4d8502Sjsg
325fb4d8502Sjsg bios = (u8 *)ISA_HOLE_VADDR(0xc0000);
326fb4d8502Sjsg
327fb4d8502Sjsg adev->bios = kzalloc(size, GFP_KERNEL);
328fb4d8502Sjsg if (adev->bios == NULL)
329fb4d8502Sjsg return false;
330fb4d8502Sjsg
331fb4d8502Sjsg memcpy_fromio(adev->bios, bios, size);
332fb4d8502Sjsg
333fb4d8502Sjsg if (!check_atom_bios(adev->bios, size)) {
334fb4d8502Sjsg kfree(adev->bios);
335fb4d8502Sjsg return false;
336fb4d8502Sjsg }
337fb4d8502Sjsg
338fb4d8502Sjsg adev->bios_size = size;
339fb4d8502Sjsg
340fb4d8502Sjsg return true;
341fb4d8502Sjsg #endif
342fb4d8502Sjsg return false;
343fb4d8502Sjsg }
344fb4d8502Sjsg #endif
345fb4d8502Sjsg
346fb4d8502Sjsg #ifdef CONFIG_ACPI
347fb4d8502Sjsg /* ATRM is used to get the BIOS on the discrete cards in
348fb4d8502Sjsg * dual-gpu systems.
349fb4d8502Sjsg */
350fb4d8502Sjsg /* retrieve the ROM in 4k blocks */
351fb4d8502Sjsg #define ATRM_BIOS_PAGE 4096
352fb4d8502Sjsg /**
353fb4d8502Sjsg * amdgpu_atrm_call - fetch a chunk of the vbios
354fb4d8502Sjsg *
355fb4d8502Sjsg * @atrm_handle: acpi ATRM handle
356fb4d8502Sjsg * @bios: vbios image pointer
357fb4d8502Sjsg * @offset: offset of vbios image data to fetch
358fb4d8502Sjsg * @len: length of vbios image data to fetch
359fb4d8502Sjsg *
360fb4d8502Sjsg * Executes ATRM to fetch a chunk of the discrete
361fb4d8502Sjsg * vbios image on PX systems (all asics).
362fb4d8502Sjsg * Returns the length of the buffer fetched.
363fb4d8502Sjsg */
amdgpu_atrm_call(acpi_handle atrm_handle,uint8_t * bios,int offset,int len)364fb4d8502Sjsg static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,
365fb4d8502Sjsg int offset, int len)
366fb4d8502Sjsg {
367fb4d8502Sjsg acpi_status status;
368fb4d8502Sjsg union acpi_object atrm_arg_elements[2], *obj;
369fb4d8502Sjsg struct acpi_object_list atrm_arg;
370fb4d8502Sjsg struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
371fb4d8502Sjsg
372fb4d8502Sjsg atrm_arg.count = 2;
373fb4d8502Sjsg atrm_arg.pointer = &atrm_arg_elements[0];
374fb4d8502Sjsg
375fb4d8502Sjsg atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;
376fb4d8502Sjsg atrm_arg_elements[0].integer.value = offset;
377fb4d8502Sjsg
378fb4d8502Sjsg atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;
379fb4d8502Sjsg atrm_arg_elements[1].integer.value = len;
380fb4d8502Sjsg
381fb4d8502Sjsg status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);
382fb4d8502Sjsg if (ACPI_FAILURE(status)) {
383*f005ef32Sjsg DRM_ERROR("failed to evaluate ATRM got %s\n", acpi_format_exception(status));
384fb4d8502Sjsg return -ENODEV;
385fb4d8502Sjsg }
386fb4d8502Sjsg
387fb4d8502Sjsg obj = (union acpi_object *)buffer.pointer;
388fb4d8502Sjsg memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);
389fb4d8502Sjsg len = obj->buffer.length;
390fb4d8502Sjsg kfree(buffer.pointer);
391fb4d8502Sjsg return len;
392fb4d8502Sjsg }
393fb4d8502Sjsg
amdgpu_atrm_get_bios(struct amdgpu_device * adev)394fb4d8502Sjsg static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
395fb4d8502Sjsg {
396fb4d8502Sjsg int ret;
397fb4d8502Sjsg int size = 256 * 1024;
398fb4d8502Sjsg int i;
399fb4d8502Sjsg struct pci_dev *pdev = NULL;
400fb4d8502Sjsg acpi_handle dhandle, atrm_handle;
401fb4d8502Sjsg acpi_status status;
402fb4d8502Sjsg bool found = false;
403fb4d8502Sjsg
404fb4d8502Sjsg /* ATRM is for the discrete card only */
405fb4d8502Sjsg if (adev->flags & AMD_IS_APU)
406fb4d8502Sjsg return false;
407fb4d8502Sjsg
408dfb3bfe4Sjsg /* ATRM is for on-platform devices only */
409dfb3bfe4Sjsg if (dev_is_removable(&adev->pdev->dev))
410dfb3bfe4Sjsg return false;
411dfb3bfe4Sjsg
4125ca02815Sjsg #ifdef notyet
413fb4d8502Sjsg while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
414fb4d8502Sjsg dhandle = ACPI_HANDLE(&pdev->dev);
415fb4d8502Sjsg if (!dhandle)
416fb4d8502Sjsg continue;
417fb4d8502Sjsg
418fb4d8502Sjsg status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
4195ca02815Sjsg if (ACPI_SUCCESS(status)) {
420fb4d8502Sjsg found = true;
421fb4d8502Sjsg break;
422fb4d8502Sjsg }
423fb4d8502Sjsg }
424fb4d8502Sjsg
425fb4d8502Sjsg if (!found) {
426fb4d8502Sjsg while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
427fb4d8502Sjsg dhandle = ACPI_HANDLE(&pdev->dev);
428fb4d8502Sjsg if (!dhandle)
429fb4d8502Sjsg continue;
430fb4d8502Sjsg
431fb4d8502Sjsg status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
4325ca02815Sjsg if (ACPI_SUCCESS(status)) {
433fb4d8502Sjsg found = true;
434fb4d8502Sjsg break;
435fb4d8502Sjsg }
436fb4d8502Sjsg }
437fb4d8502Sjsg }
4385ca02815Sjsg #else
4395ca02815Sjsg {
4405ca02815Sjsg pdev = adev->pdev;
4415ca02815Sjsg dhandle = ACPI_HANDLE(&pdev->dev);
4425ca02815Sjsg
4435ca02815Sjsg if (dhandle) {
4445ca02815Sjsg status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);
4455ca02815Sjsg if (ACPI_SUCCESS(status)) {
4465ca02815Sjsg found = true;
4475ca02815Sjsg }
4485ca02815Sjsg }
4495ca02815Sjsg }
4505ca02815Sjsg #endif
451fb4d8502Sjsg
452fb4d8502Sjsg if (!found)
453fb4d8502Sjsg return false;
4541bb76ff1Sjsg pci_dev_put(pdev);
455fb4d8502Sjsg
456fb4d8502Sjsg adev->bios = kmalloc(size, GFP_KERNEL);
457fb4d8502Sjsg if (!adev->bios) {
4585ca02815Sjsg dev_err(adev->dev, "Unable to allocate bios\n");
459fb4d8502Sjsg return false;
460fb4d8502Sjsg }
461fb4d8502Sjsg
462fb4d8502Sjsg for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
463fb4d8502Sjsg ret = amdgpu_atrm_call(atrm_handle,
464fb4d8502Sjsg adev->bios,
465fb4d8502Sjsg (i * ATRM_BIOS_PAGE),
466fb4d8502Sjsg ATRM_BIOS_PAGE);
467fb4d8502Sjsg if (ret < ATRM_BIOS_PAGE)
468fb4d8502Sjsg break;
469fb4d8502Sjsg }
470fb4d8502Sjsg
471fb4d8502Sjsg if (!check_atom_bios(adev->bios, size)) {
472fb4d8502Sjsg kfree(adev->bios);
473fb4d8502Sjsg return false;
474fb4d8502Sjsg }
475fb4d8502Sjsg adev->bios_size = size;
476fb4d8502Sjsg return true;
477fb4d8502Sjsg }
478fb4d8502Sjsg #else
amdgpu_atrm_get_bios(struct amdgpu_device * adev)479fb4d8502Sjsg static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
480fb4d8502Sjsg {
481fb4d8502Sjsg return false;
482fb4d8502Sjsg }
483fb4d8502Sjsg #endif
484fb4d8502Sjsg
amdgpu_read_disabled_bios(struct amdgpu_device * adev)485fb4d8502Sjsg static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)
486fb4d8502Sjsg {
487fb4d8502Sjsg if (adev->flags & AMD_IS_APU)
488fb4d8502Sjsg return igp_read_bios_from_vram(adev);
489fb4d8502Sjsg else
4905ca02815Sjsg return (!adev->asic_funcs || !adev->asic_funcs->read_disabled_bios) ?
4915ca02815Sjsg false : amdgpu_asic_read_disabled_bios(adev);
492fb4d8502Sjsg }
493fb4d8502Sjsg
494fb4d8502Sjsg #ifdef CONFIG_ACPI
amdgpu_acpi_vfct_bios(struct amdgpu_device * adev)495fb4d8502Sjsg static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
496fb4d8502Sjsg {
497fb4d8502Sjsg struct acpi_table_header *hdr;
498fb4d8502Sjsg acpi_size tbl_size;
499fb4d8502Sjsg UEFI_ACPI_VFCT *vfct;
500*f005ef32Sjsg unsigned int offset;
501fb4d8502Sjsg
502fb4d8502Sjsg if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))
503fb4d8502Sjsg return false;
504fb4d8502Sjsg tbl_size = hdr->length;
505fb4d8502Sjsg if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {
5065ca02815Sjsg dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");
507fb4d8502Sjsg return false;
508fb4d8502Sjsg }
509fb4d8502Sjsg
510fb4d8502Sjsg vfct = (UEFI_ACPI_VFCT *)hdr;
511fb4d8502Sjsg offset = vfct->VBIOSImageOffset;
512fb4d8502Sjsg
513fb4d8502Sjsg while (offset < tbl_size) {
514fb4d8502Sjsg GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);
515fb4d8502Sjsg VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;
516fb4d8502Sjsg
517fb4d8502Sjsg offset += sizeof(VFCT_IMAGE_HEADER);
518fb4d8502Sjsg if (offset > tbl_size) {
5195ca02815Sjsg dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");
520fb4d8502Sjsg return false;
521fb4d8502Sjsg }
522fb4d8502Sjsg
523fb4d8502Sjsg offset += vhdr->ImageLength;
524fb4d8502Sjsg if (offset > tbl_size) {
5255ca02815Sjsg dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");
526fb4d8502Sjsg return false;
527fb4d8502Sjsg }
528fb4d8502Sjsg
529fb4d8502Sjsg if (vhdr->ImageLength &&
530fb4d8502Sjsg vhdr->PCIBus == adev->pdev->bus->number &&
531fb4d8502Sjsg vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&
532fb4d8502Sjsg vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&
533fb4d8502Sjsg vhdr->VendorID == adev->pdev->vendor &&
534fb4d8502Sjsg vhdr->DeviceID == adev->pdev->device) {
535fb4d8502Sjsg adev->bios = kmemdup(&vbios->VbiosContent,
536fb4d8502Sjsg vhdr->ImageLength,
537fb4d8502Sjsg GFP_KERNEL);
538fb4d8502Sjsg
539fb4d8502Sjsg if (!check_atom_bios(adev->bios, vhdr->ImageLength)) {
540fb4d8502Sjsg kfree(adev->bios);
541fb4d8502Sjsg return false;
542fb4d8502Sjsg }
543fb4d8502Sjsg adev->bios_size = vhdr->ImageLength;
544fb4d8502Sjsg return true;
545fb4d8502Sjsg }
546fb4d8502Sjsg }
547fb4d8502Sjsg
5485ca02815Sjsg dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");
549fb4d8502Sjsg return false;
550fb4d8502Sjsg }
551fb4d8502Sjsg #else
amdgpu_acpi_vfct_bios(struct amdgpu_device * adev)552fb4d8502Sjsg static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)
553fb4d8502Sjsg {
554fb4d8502Sjsg return false;
555fb4d8502Sjsg }
556fb4d8502Sjsg #endif
557fb4d8502Sjsg
amdgpu_get_bios(struct amdgpu_device * adev)558fb4d8502Sjsg bool amdgpu_get_bios(struct amdgpu_device *adev)
559fb4d8502Sjsg {
560ad8b1aafSjsg if (amdgpu_atrm_get_bios(adev)) {
561ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from ATRM\n");
562fb4d8502Sjsg goto success;
563ad8b1aafSjsg }
564fb4d8502Sjsg
565ad8b1aafSjsg if (amdgpu_acpi_vfct_bios(adev)) {
566ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from VFCT\n");
567fb4d8502Sjsg goto success;
568ad8b1aafSjsg }
569fb4d8502Sjsg
570ad8b1aafSjsg if (igp_read_bios_from_vram(adev)) {
571ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");
572fb4d8502Sjsg goto success;
573ad8b1aafSjsg }
574fb4d8502Sjsg
575ad8b1aafSjsg if (amdgpu_read_bios(adev)) {
576ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");
577fb4d8502Sjsg goto success;
578ad8b1aafSjsg }
579fb4d8502Sjsg
580ad8b1aafSjsg if (amdgpu_read_bios_from_rom(adev)) {
581ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from ROM\n");
582fb4d8502Sjsg goto success;
583ad8b1aafSjsg }
584fb4d8502Sjsg
585ad8b1aafSjsg if (amdgpu_read_disabled_bios(adev)) {
586ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n");
587fb4d8502Sjsg goto success;
588ad8b1aafSjsg }
589fb4d8502Sjsg
590ad8b1aafSjsg if (amdgpu_read_platform_bios(adev)) {
591ad8b1aafSjsg dev_info(adev->dev, "Fetched VBIOS from platform\n");
592fb4d8502Sjsg goto success;
593ad8b1aafSjsg }
594fb4d8502Sjsg
5955ca02815Sjsg dev_err(adev->dev, "Unable to locate a BIOS ROM\n");
596fb4d8502Sjsg return false;
597fb4d8502Sjsg
598fb4d8502Sjsg success:
599*f005ef32Sjsg adev->is_atom_fw = adev->asic_type >= CHIP_VEGA10;
600fb4d8502Sjsg return true;
601fb4d8502Sjsg }
6021bb76ff1Sjsg
6031bb76ff1Sjsg /* helper function for soc15 and onwards to read bios from rom */
amdgpu_soc15_read_bios_from_rom(struct amdgpu_device * adev,u8 * bios,u32 length_bytes)6041bb76ff1Sjsg bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,
6051bb76ff1Sjsg u8 *bios, u32 length_bytes)
6061bb76ff1Sjsg {
6071bb76ff1Sjsg u32 *dw_ptr;
6081bb76ff1Sjsg u32 i, length_dw;
6091bb76ff1Sjsg u32 rom_offset;
6101bb76ff1Sjsg u32 rom_index_offset;
6111bb76ff1Sjsg u32 rom_data_offset;
6121bb76ff1Sjsg
6131bb76ff1Sjsg if (bios == NULL)
6141bb76ff1Sjsg return false;
6151bb76ff1Sjsg if (length_bytes == 0)
6161bb76ff1Sjsg return false;
6171bb76ff1Sjsg /* APU vbios image is part of sbios image */
6181bb76ff1Sjsg if (adev->flags & AMD_IS_APU)
6191bb76ff1Sjsg return false;
6201bb76ff1Sjsg if (!adev->smuio.funcs ||
6211bb76ff1Sjsg !adev->smuio.funcs->get_rom_index_offset ||
6221bb76ff1Sjsg !adev->smuio.funcs->get_rom_data_offset)
6231bb76ff1Sjsg return false;
6241bb76ff1Sjsg
6251bb76ff1Sjsg dw_ptr = (u32 *)bios;
626*f005ef32Sjsg length_dw = ALIGN(length_bytes, 4) / 4;
6271bb76ff1Sjsg
6281bb76ff1Sjsg rom_index_offset =
6291bb76ff1Sjsg adev->smuio.funcs->get_rom_index_offset(adev);
6301bb76ff1Sjsg rom_data_offset =
6311bb76ff1Sjsg adev->smuio.funcs->get_rom_data_offset(adev);
6321bb76ff1Sjsg
6331bb76ff1Sjsg if (adev->nbio.funcs &&
6341bb76ff1Sjsg adev->nbio.funcs->get_rom_offset) {
6351bb76ff1Sjsg rom_offset = adev->nbio.funcs->get_rom_offset(adev);
6361bb76ff1Sjsg rom_offset = rom_offset << 17;
6371bb76ff1Sjsg } else {
6381bb76ff1Sjsg rom_offset = 0;
6391bb76ff1Sjsg }
6401bb76ff1Sjsg
6411bb76ff1Sjsg /* set rom index to rom_offset */
6421bb76ff1Sjsg WREG32(rom_index_offset, rom_offset);
6431bb76ff1Sjsg /* read out the rom data */
6441bb76ff1Sjsg for (i = 0; i < length_dw; i++)
6451bb76ff1Sjsg dw_ptr[i] = RREG32(rom_data_offset);
6461bb76ff1Sjsg
6471bb76ff1Sjsg return true;
6481bb76ff1Sjsg }
649