162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Exceptions for specific devices. Usually work-arounds for fatal design flaws. 462306a36Sopenharmony_ci * Derived from fixup.c of i386 tree. 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/pci.h> 862306a36Sopenharmony_ci#include <linux/init.h> 962306a36Sopenharmony_ci#include <linux/vgaarb.h> 1062306a36Sopenharmony_ci#include <linux/screen_info.h> 1162306a36Sopenharmony_ci#include <asm/uv/uv.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci/* 1462306a36Sopenharmony_ci * Fixup to mark boot BIOS video selected by BIOS before it changes 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * From information provided by "Jon Smirl" <jonsmirl@gmail.com> 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * The standard boot ROM sequence for an x86 machine uses the BIOS 1962306a36Sopenharmony_ci * to select an initial video card for boot display. This boot video 2062306a36Sopenharmony_ci * card will have its BIOS copied to 0xC0000 in system RAM. 2162306a36Sopenharmony_ci * IORESOURCE_ROM_SHADOW is used to associate the boot video 2262306a36Sopenharmony_ci * card with this copy. On laptops this copy has to be used since 2362306a36Sopenharmony_ci * the main ROM may be compressed or combined with another image. 2462306a36Sopenharmony_ci * See pci_map_rom() for use of this flag. Before marking the device 2562306a36Sopenharmony_ci * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set 2662306a36Sopenharmony_ci * by either arch code or vga-arbitration; if so only apply the fixup to this 2762306a36Sopenharmony_ci * already-determined primary video card. 2862306a36Sopenharmony_ci */ 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistatic void pci_fixup_video(struct pci_dev *pdev) 3162306a36Sopenharmony_ci{ 3262306a36Sopenharmony_ci struct pci_dev *bridge; 3362306a36Sopenharmony_ci struct pci_bus *bus; 3462306a36Sopenharmony_ci u16 config; 3562306a36Sopenharmony_ci struct resource *res; 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci if (is_uv_system()) 3862306a36Sopenharmony_ci return; 3962306a36Sopenharmony_ci /* Maybe, this machine supports legacy memory map. */ 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci /* Is VGA routed to us? */ 4262306a36Sopenharmony_ci bus = pdev->bus; 4362306a36Sopenharmony_ci while (bus) { 4462306a36Sopenharmony_ci bridge = bus->self; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci /* 4762306a36Sopenharmony_ci * From information provided by 4862306a36Sopenharmony_ci * "David Miller" <davem@davemloft.net> 4962306a36Sopenharmony_ci * The bridge control register is valid for PCI header 5062306a36Sopenharmony_ci * type BRIDGE, or CARDBUS. Host to PCI controllers use 5162306a36Sopenharmony_ci * PCI header type NORMAL. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_ci if (bridge && (pci_is_bridge(bridge))) { 5462306a36Sopenharmony_ci pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, 5562306a36Sopenharmony_ci &config); 5662306a36Sopenharmony_ci if (!(config & PCI_BRIDGE_CTL_VGA)) 5762306a36Sopenharmony_ci return; 5862306a36Sopenharmony_ci } 5962306a36Sopenharmony_ci bus = bus->parent; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci if (!vga_default_device() || pdev == vga_default_device()) { 6262306a36Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &config); 6362306a36Sopenharmony_ci if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { 6462306a36Sopenharmony_ci res = &pdev->resource[PCI_ROM_RESOURCE]; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci pci_disable_rom(pdev); 6762306a36Sopenharmony_ci if (res->parent) 6862306a36Sopenharmony_ci release_resource(res); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci res->start = 0xC0000; 7162306a36Sopenharmony_ci res->end = res->start + 0x20000 - 1; 7262306a36Sopenharmony_ci res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW | 7362306a36Sopenharmony_ci IORESOURCE_PCI_FIXED; 7462306a36Sopenharmony_ci dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n", 7562306a36Sopenharmony_ci res); 7662306a36Sopenharmony_ci } 7762306a36Sopenharmony_ci } 7862306a36Sopenharmony_ci} 7962306a36Sopenharmony_ciDECLARE_PCI_FIXUP_CLASS_HEADER(PCI_ANY_ID, PCI_ANY_ID, 8062306a36Sopenharmony_ci PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); 81