/* * Copyright 2008 Advanced Micro Devices, Inc. * Copyright 2008 Red Hat Inc. * Copyright 2009 Jerome Glisse. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR * OTHER DEALINGS IN THE SOFTWARE. * * Authors: Dave Airlie * Alex Deucher * Jerome Glisse
*/
/* Check if current bios is an ATOM BIOS. * Return true if it is ATOM BIOS. Otherwise, return false.
*/ staticbool check_atom_bios(struct amdgpu_device *adev, size_t size)
{
uint16_t tmp, bios_header_start;
uint8_t *bios = adev->bios;
if (!bios || size < 0x49) {
dev_dbg(adev->dev, "VBIOS mem is null or mem size is wrong\n"); returnfalse;
}
/* If you boot an IGP board with a discrete card as the primary, * the IGP rom is not accessible via the rom bar as the IGP rom is * part of the system bios. On boot, the system bios puts a * copy of the igp rom at the start of vram if a discrete card is * present. * For SR-IOV, the vbios image is also put in VRAM in the VF.
*/ staticbool amdgpu_read_bios_from_vram(struct amdgpu_device *adev)
{
uint8_t __iomem *bios;
resource_size_t vram_base;
resource_size_t size = 256 * 1024; /* ??? */
if (!(adev->flags & AMD_IS_APU)) if (amdgpu_device_need_post(adev)) returnfalse;
/* FB BAR not enabled */ if (pci_resource_len(adev->pdev, 0) == 0) returnfalse;
adev->bios = NULL; /* XXX: some cards may return 0 for rom size? ddx has a workaround */
bios = pci_map_rom(adev->pdev, &size); if (!bios) returnfalse;
if ((!AMD_IS_VALID_VBIOS(header)) ||
memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],
AMD_VBIOS_SIGNATURE,
strlen(AMD_VBIOS_SIGNATURE)) != 0) returnfalse;
/* valid vbios, go on */
len = AMD_VBIOS_LENGTH(header);
len = ALIGN(len, 4);
adev->bios = kmalloc(len, GFP_KERNEL); if (!adev->bios) {
DRM_ERROR("no memory to allocate for BIOS\n"); returnfalse;
}
adev->bios_size = len;
if (!check_atom_bios(adev, romlen)) goto free_bios;
adev->bios_size = romlen;
returntrue;
free_bios:
amdgpu_bios_release(adev);
returnfalse;
}
#ifdef CONFIG_ACPI /* ATRM is used to get the BIOS on the discrete cards in * dual-gpu systems.
*/ /* retrieve the ROM in 4k blocks */ #define ATRM_BIOS_PAGE 4096 /** * amdgpu_atrm_call - fetch a chunk of the vbios * * @atrm_handle: acpi ATRM handle * @bios: vbios image pointer * @offset: offset of vbios image data to fetch * @len: length of vbios image data to fetch * * Executes ATRM to fetch a chunk of the discrete * vbios image on PX systems (all asics). * Returns the length of the buffer fetched.
*/ staticint amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios, int offset, int len)
{
acpi_status status; union acpi_object atrm_arg_elements[2], *obj; struct acpi_object_list atrm_arg; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};
staticbool amdgpu_atrm_get_bios(struct amdgpu_device *adev)
{ int ret; int size = 256 * 1024; int i; struct pci_dev *pdev = NULL;
acpi_handle dhandle, atrm_handle;
acpi_status status; bool found = false;
/* ATRM is for on-platform devices only */ if (dev_is_removable(&adev->pdev->dev)) returnfalse;
while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) { if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&
(pdev->class != PCI_CLASS_DISPLAY_OTHER << 8)) continue;
dhandle = ACPI_HANDLE(&pdev->dev); if (!dhandle) continue;
status = acpi_get_handle(dhandle, "ATRM", &atrm_handle); if (ACPI_SUCCESS(status)) {
found = true; break;
}
}
if (!found) returnfalse;
pci_dev_put(pdev);
adev->bios = kmalloc(size, GFP_KERNEL); if (!adev->bios) {
dev_err(adev->dev, "Unable to allocate bios\n"); returnfalse;
}
for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {
ret = amdgpu_atrm_call(atrm_handle,
adev->bios,
(i * ATRM_BIOS_PAGE),
ATRM_BIOS_PAGE); if (ret < ATRM_BIOS_PAGE) break;
}
if (adev->flags & AMD_IS_APU)
found = amdgpu_get_bios_apu(adev); else
found = amdgpu_get_bios_dgpu(adev);
if (found)
adev->is_atom_fw = adev->asic_type >= CHIP_VEGA10;
return found;
}
/* helper function for soc15 and onwards to read bios from rom */ bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,
u8 *bios, u32 length_bytes)
{
u32 *dw_ptr;
u32 i, length_dw;
u32 rom_offset;
u32 rom_index_offset;
u32 rom_data_offset;
if (bios == NULL) returnfalse; if (length_bytes == 0) returnfalse; /* APU vbios image is part of sbios image */ if (adev->flags & AMD_IS_APU) returnfalse; if (!adev->smuio.funcs ||
!adev->smuio.funcs->get_rom_index_offset ||
!adev->smuio.funcs->get_rom_data_offset) returnfalse;
/* set rom index to rom_offset */
WREG32(rom_index_offset, rom_offset); /* read out the rom data */ for (i = 0; i < length_dw; i++)
dw_ptr[i] = RREG32(rom_data_offset);
returntrue;
}
Messung V0.5
¤ Dauer der Verarbeitung: 0.2 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.