Path: blob/master/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c
49743 views
/*1* Copyright 2008 Advanced Micro Devices, Inc.2* Copyright 2008 Red Hat Inc.3* Copyright 2009 Jerome Glisse.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the "Software"),7* to deal in the Software without restriction, including without limitation8* the rights to use, copy, modify, merge, publish, distribute, sublicense,9* and/or sell copies of the Software, and to permit persons to whom the10* Software is furnished to do so, subject to the following conditions:11*12* The above copyright notice and this permission notice shall be included in13* all copies or substantial portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR19* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,20* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR21* OTHER DEALINGS IN THE SOFTWARE.22*23* Authors: Dave Airlie24* Alex Deucher25* Jerome Glisse26*/2728#include "amdgpu.h"29#include "atom.h"3031#include <linux/device.h>32#include <linux/pci.h>33#include <linux/slab.h>34#include <linux/acpi.h>35/*36* BIOS.37*/3839#define AMD_VBIOS_SIGNATURE " 761295520"40#define AMD_VBIOS_SIGNATURE_OFFSET 0x3041#define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE)42#define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE)43#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA)44#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9)4546/* Check if current bios is an ATOM BIOS.47* Return true if it is ATOM BIOS. Otherwise, return false.48*/49static bool check_atom_bios(struct amdgpu_device *adev, size_t size)50{51uint16_t tmp, bios_header_start;52uint8_t *bios = adev->bios;5354if (!bios || size < 0x49) {55dev_dbg(adev->dev, "VBIOS mem is null or mem size is wrong\n");56return false;57}5859if (!AMD_IS_VALID_VBIOS(bios)) {60dev_dbg(adev->dev, "VBIOS signature incorrect %x %x\n", bios[0],61bios[1]);62return false;63}6465bios_header_start = bios[0x48] | (bios[0x49] << 8);66if (!bios_header_start) {67dev_dbg(adev->dev, "Can't locate VBIOS header\n");68return false;69}7071tmp = bios_header_start + 4;72if (size < tmp) {73dev_dbg(adev->dev, "VBIOS header is broken\n");74return false;75}7677if (!memcmp(bios + tmp, "ATOM", 4) ||78!memcmp(bios + tmp, "MOTA", 4)) {79dev_dbg(adev->dev, "ATOMBIOS detected\n");80return true;81}8283return false;84}8586void amdgpu_bios_release(struct amdgpu_device *adev)87{88kfree(adev->bios);89adev->bios = NULL;90adev->bios_size = 0;91}9293/* If you boot an IGP board with a discrete card as the primary,94* the IGP rom is not accessible via the rom bar as the IGP rom is95* part of the system bios. On boot, the system bios puts a96* copy of the igp rom at the start of vram if a discrete card is97* present.98* For SR-IOV, if dynamic critical region is not enabled,99* the vbios image is also put at the start of VRAM in the VF.100*/101static bool amdgpu_read_bios_from_vram(struct amdgpu_device *adev)102{103uint8_t __iomem *bios = NULL;104resource_size_t vram_base;105u32 size = 256U * 1024U; /* ??? */106107if (!(adev->flags & AMD_IS_APU))108if (amdgpu_device_need_post(adev))109return false;110111/* FB BAR not enabled */112if (pci_resource_len(adev->pdev, 0) == 0)113return false;114115adev->bios = NULL;116vram_base = pci_resource_start(adev->pdev, 0);117118adev->bios = kmalloc(size, GFP_KERNEL);119if (!adev->bios)120return false;121122/* For SRIOV with dynamic critical region is enabled,123* the vbios image is put at a dynamic offset of VRAM in the VF.124* If dynamic critical region is disabled, follow the existing logic as on baremetal.125*/126if (amdgpu_sriov_vf(adev) && adev->virt.is_dynamic_crit_regn_enabled) {127if (amdgpu_virt_get_dynamic_data_info(adev,128AMD_SRIOV_MSG_VBIOS_IMG_TABLE_ID, adev->bios, &size)) {129amdgpu_bios_release(adev);130return false;131}132} else {133bios = ioremap_wc(vram_base, size);134if (!bios) {135amdgpu_bios_release(adev);136return false;137}138139memcpy_fromio(adev->bios, bios, size);140iounmap(bios);141}142143adev->bios_size = size;144145if (!check_atom_bios(adev, size)) {146amdgpu_bios_release(adev);147return false;148}149150return true;151}152153bool amdgpu_read_bios(struct amdgpu_device *adev)154{155uint8_t __iomem *bios;156size_t size;157158adev->bios = NULL;159/* XXX: some cards may return 0 for rom size? ddx has a workaround */160bios = pci_map_rom(adev->pdev, &size);161if (!bios)162return false;163164adev->bios = kzalloc(size, GFP_KERNEL);165if (adev->bios == NULL) {166pci_unmap_rom(adev->pdev, bios);167return false;168}169adev->bios_size = size;170memcpy_fromio(adev->bios, bios, size);171pci_unmap_rom(adev->pdev, bios);172173if (!check_atom_bios(adev, size)) {174amdgpu_bios_release(adev);175return false;176}177178return true;179}180181static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev)182{183u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0};184int len;185186if (!adev->asic_funcs || !adev->asic_funcs->read_bios_from_rom)187return false;188189/* validate VBIOS signature */190if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false)191return false;192header[AMD_VBIOS_SIGNATURE_END] = 0;193194if ((!AMD_IS_VALID_VBIOS(header)) ||195memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET],196AMD_VBIOS_SIGNATURE,197strlen(AMD_VBIOS_SIGNATURE)) != 0)198return false;199200/* valid vbios, go on */201len = AMD_VBIOS_LENGTH(header);202len = ALIGN(len, 4);203adev->bios = kmalloc(len, GFP_KERNEL);204if (!adev->bios) {205DRM_ERROR("no memory to allocate for BIOS\n");206return false;207}208adev->bios_size = len;209210/* read complete BIOS */211amdgpu_asic_read_bios_from_rom(adev, adev->bios, len);212213if (!check_atom_bios(adev, len)) {214amdgpu_bios_release(adev);215return false;216}217218return true;219}220221static bool amdgpu_read_platform_bios(struct amdgpu_device *adev)222{223phys_addr_t rom = adev->pdev->rom;224size_t romlen = adev->pdev->romlen;225void __iomem *bios;226227adev->bios = NULL;228229if (!rom || romlen == 0)230return false;231232adev->bios = kzalloc(romlen, GFP_KERNEL);233if (!adev->bios)234return false;235236bios = ioremap(rom, romlen);237if (!bios)238goto free_bios;239240memcpy_fromio(adev->bios, bios, romlen);241iounmap(bios);242243if (!check_atom_bios(adev, romlen))244goto free_bios;245246adev->bios_size = romlen;247248return true;249free_bios:250amdgpu_bios_release(adev);251252return false;253}254255#ifdef CONFIG_ACPI256/* ATRM is used to get the BIOS on the discrete cards in257* dual-gpu systems.258*/259/* retrieve the ROM in 4k blocks */260#define ATRM_BIOS_PAGE 4096261/**262* amdgpu_atrm_call - fetch a chunk of the vbios263*264* @atrm_handle: acpi ATRM handle265* @bios: vbios image pointer266* @offset: offset of vbios image data to fetch267* @len: length of vbios image data to fetch268*269* Executes ATRM to fetch a chunk of the discrete270* vbios image on PX systems (all asics).271* Returns the length of the buffer fetched.272*/273static int amdgpu_atrm_call(acpi_handle atrm_handle, uint8_t *bios,274int offset, int len)275{276acpi_status status;277union acpi_object atrm_arg_elements[2], *obj;278struct acpi_object_list atrm_arg;279struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL};280281atrm_arg.count = 2;282atrm_arg.pointer = &atrm_arg_elements[0];283284atrm_arg_elements[0].type = ACPI_TYPE_INTEGER;285atrm_arg_elements[0].integer.value = offset;286287atrm_arg_elements[1].type = ACPI_TYPE_INTEGER;288atrm_arg_elements[1].integer.value = len;289290status = acpi_evaluate_object(atrm_handle, NULL, &atrm_arg, &buffer);291if (ACPI_FAILURE(status)) {292DRM_ERROR("failed to evaluate ATRM got %s\n", acpi_format_exception(status));293return -ENODEV;294}295296obj = (union acpi_object *)buffer.pointer;297memcpy(bios+offset, obj->buffer.pointer, obj->buffer.length);298len = obj->buffer.length;299kfree(buffer.pointer);300return len;301}302303static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)304{305int ret;306int size = 256 * 1024;307int i;308struct pci_dev *pdev = NULL;309acpi_handle dhandle, atrm_handle;310acpi_status status;311bool found = false;312313/* ATRM is for on-platform devices only */314if (dev_is_removable(&adev->pdev->dev))315return false;316317while ((pdev = pci_get_base_class(PCI_BASE_CLASS_DISPLAY, pdev))) {318if ((pdev->class != PCI_CLASS_DISPLAY_VGA << 8) &&319(pdev->class != PCI_CLASS_DISPLAY_OTHER << 8))320continue;321322dhandle = ACPI_HANDLE(&pdev->dev);323if (!dhandle)324continue;325326status = acpi_get_handle(dhandle, "ATRM", &atrm_handle);327if (ACPI_SUCCESS(status)) {328found = true;329break;330}331}332333if (!found)334return false;335pci_dev_put(pdev);336337adev->bios = kmalloc(size, GFP_KERNEL);338if (!adev->bios) {339dev_err(adev->dev, "Unable to allocate bios\n");340return false;341}342343for (i = 0; i < size / ATRM_BIOS_PAGE; i++) {344ret = amdgpu_atrm_call(atrm_handle,345adev->bios,346(i * ATRM_BIOS_PAGE),347ATRM_BIOS_PAGE);348if (ret < ATRM_BIOS_PAGE)349break;350}351352if (!check_atom_bios(adev, size)) {353amdgpu_bios_release(adev);354return false;355}356adev->bios_size = size;357return true;358}359#else360static inline bool amdgpu_atrm_get_bios(struct amdgpu_device *adev)361{362return false;363}364#endif365366static bool amdgpu_read_disabled_bios(struct amdgpu_device *adev)367{368return (!adev->asic_funcs || !adev->asic_funcs->read_disabled_bios) ?369false : amdgpu_asic_read_disabled_bios(adev);370}371372#ifdef CONFIG_ACPI373static bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)374{375struct acpi_table_header *hdr;376acpi_size tbl_size;377UEFI_ACPI_VFCT *vfct;378unsigned int offset;379380if (!ACPI_SUCCESS(acpi_get_table("VFCT", 1, &hdr)))381return false;382tbl_size = hdr->length;383if (tbl_size < sizeof(UEFI_ACPI_VFCT)) {384dev_info(adev->dev, "ACPI VFCT table present but broken (too short #1),skipping\n");385return false;386}387388vfct = (UEFI_ACPI_VFCT *)hdr;389offset = vfct->VBIOSImageOffset;390391while (offset < tbl_size) {392GOP_VBIOS_CONTENT *vbios = (GOP_VBIOS_CONTENT *)((char *)hdr + offset);393VFCT_IMAGE_HEADER *vhdr = &vbios->VbiosHeader;394395offset += sizeof(VFCT_IMAGE_HEADER);396if (offset > tbl_size) {397dev_info(adev->dev, "ACPI VFCT image header truncated,skipping\n");398return false;399}400401offset += vhdr->ImageLength;402if (offset > tbl_size) {403dev_info(adev->dev, "ACPI VFCT image truncated,skipping\n");404return false;405}406407if (vhdr->ImageLength &&408vhdr->PCIBus == adev->pdev->bus->number &&409vhdr->PCIDevice == PCI_SLOT(adev->pdev->devfn) &&410vhdr->PCIFunction == PCI_FUNC(adev->pdev->devfn) &&411vhdr->VendorID == adev->pdev->vendor &&412vhdr->DeviceID == adev->pdev->device) {413adev->bios = kmemdup(&vbios->VbiosContent,414vhdr->ImageLength,415GFP_KERNEL);416417if (!check_atom_bios(adev, vhdr->ImageLength)) {418amdgpu_bios_release(adev);419return false;420}421adev->bios_size = vhdr->ImageLength;422return true;423}424}425426dev_info(adev->dev, "ACPI VFCT table present but broken (too short #2),skipping\n");427return false;428}429#else430static inline bool amdgpu_acpi_vfct_bios(struct amdgpu_device *adev)431{432return false;433}434#endif435436static bool amdgpu_get_bios_apu(struct amdgpu_device *adev)437{438if (amdgpu_acpi_vfct_bios(adev)) {439dev_info(adev->dev, "Fetched VBIOS from VFCT\n");440goto success;441}442443if (amdgpu_read_bios_from_vram(adev)) {444dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");445goto success;446}447448if (amdgpu_read_bios(adev)) {449dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");450goto success;451}452453if (amdgpu_read_platform_bios(adev)) {454dev_info(adev->dev, "Fetched VBIOS from platform\n");455goto success;456}457458dev_err(adev->dev, "Unable to locate a BIOS ROM\n");459return false;460461success:462return true;463}464465static bool amdgpu_prefer_rom_resource(struct amdgpu_device *adev)466{467struct resource *res = &adev->pdev->resource[PCI_ROM_RESOURCE];468469return (res->flags & IORESOURCE_ROM_SHADOW);470}471472static bool amdgpu_get_bios_dgpu(struct amdgpu_device *adev)473{474if (amdgpu_atrm_get_bios(adev)) {475dev_info(adev->dev, "Fetched VBIOS from ATRM\n");476goto success;477}478479if (amdgpu_acpi_vfct_bios(adev)) {480dev_info(adev->dev, "Fetched VBIOS from VFCT\n");481goto success;482}483484/* this is required for SR-IOV */485if (amdgpu_read_bios_from_vram(adev)) {486dev_info(adev->dev, "Fetched VBIOS from VRAM BAR\n");487goto success;488}489490if (amdgpu_prefer_rom_resource(adev)) {491if (amdgpu_read_bios(adev)) {492dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");493goto success;494}495496if (amdgpu_read_platform_bios(adev)) {497dev_info(adev->dev, "Fetched VBIOS from platform\n");498goto success;499}500501} else {502if (amdgpu_read_platform_bios(adev)) {503dev_info(adev->dev, "Fetched VBIOS from platform\n");504goto success;505}506507if (amdgpu_read_bios(adev)) {508dev_info(adev->dev, "Fetched VBIOS from ROM BAR\n");509goto success;510}511}512513if (amdgpu_read_bios_from_rom(adev)) {514dev_info(adev->dev, "Fetched VBIOS from ROM\n");515goto success;516}517518if (amdgpu_read_disabled_bios(adev)) {519dev_info(adev->dev, "Fetched VBIOS from disabled ROM BAR\n");520goto success;521}522523dev_err(adev->dev, "Unable to locate a BIOS ROM\n");524return false;525526success:527return true;528}529530bool amdgpu_get_bios(struct amdgpu_device *adev)531{532bool found;533534if (adev->flags & AMD_IS_APU)535found = amdgpu_get_bios_apu(adev);536else537found = amdgpu_get_bios_dgpu(adev);538539if (found)540adev->is_atom_fw = adev->asic_type >= CHIP_VEGA10;541542return found;543}544545/* helper function for soc15 and onwards to read bios from rom */546bool amdgpu_soc15_read_bios_from_rom(struct amdgpu_device *adev,547u8 *bios, u32 length_bytes)548{549u32 *dw_ptr;550u32 i, length_dw;551u32 rom_offset;552u32 rom_index_offset;553u32 rom_data_offset;554555if (bios == NULL)556return false;557if (length_bytes == 0)558return false;559/* APU vbios image is part of sbios image */560if (adev->flags & AMD_IS_APU)561return false;562if (!adev->smuio.funcs ||563!adev->smuio.funcs->get_rom_index_offset ||564!adev->smuio.funcs->get_rom_data_offset)565return false;566567dw_ptr = (u32 *)bios;568length_dw = ALIGN(length_bytes, 4) / 4;569570rom_index_offset =571adev->smuio.funcs->get_rom_index_offset(adev);572rom_data_offset =573adev->smuio.funcs->get_rom_data_offset(adev);574575if (adev->nbio.funcs &&576adev->nbio.funcs->get_rom_offset) {577rom_offset = adev->nbio.funcs->get_rom_offset(adev);578rom_offset = rom_offset << 17;579} else {580rom_offset = 0;581}582583/* set rom index to rom_offset */584WREG32(rom_index_offset, rom_offset);585/* read out the rom data */586for (i = 0; i < length_dw; i++)587dw_ptr[i] = RREG32(rom_data_offset);588589return true;590}591592593