18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Exceptions for specific devices. Usually work-arounds for fatal design flaws. 48c2ecf20Sopenharmony_ci * Derived from fixup.c of i386 tree. 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <linux/pci.h> 88c2ecf20Sopenharmony_ci#include <linux/init.h> 98c2ecf20Sopenharmony_ci#include <linux/vgaarb.h> 108c2ecf20Sopenharmony_ci#include <linux/screen_info.h> 118c2ecf20Sopenharmony_ci#include <asm/uv/uv.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ci/* 148c2ecf20Sopenharmony_ci * Fixup to mark boot BIOS video selected by BIOS before it changes 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * From information provided by "Jon Smirl" <jonsmirl@gmail.com> 178c2ecf20Sopenharmony_ci * 188c2ecf20Sopenharmony_ci * The standard boot ROM sequence for an x86 machine uses the BIOS 198c2ecf20Sopenharmony_ci * to select an initial video card for boot display. This boot video 208c2ecf20Sopenharmony_ci * card will have its BIOS copied to 0xC0000 in system RAM. 218c2ecf20Sopenharmony_ci * IORESOURCE_ROM_SHADOW is used to associate the boot video 228c2ecf20Sopenharmony_ci * card with this copy. On laptops this copy has to be used since 238c2ecf20Sopenharmony_ci * the main ROM may be compressed or combined with another image. 248c2ecf20Sopenharmony_ci * See pci_map_rom() for use of this flag. Before marking the device 258c2ecf20Sopenharmony_ci * with IORESOURCE_ROM_SHADOW check if a vga_default_device is already set 268c2ecf20Sopenharmony_ci * by either arch code or vga-arbitration; if so only apply the fixup to this 278c2ecf20Sopenharmony_ci * already-determined primary video card. 288c2ecf20Sopenharmony_ci */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_cistatic void pci_fixup_video(struct pci_dev *pdev) 318c2ecf20Sopenharmony_ci{ 328c2ecf20Sopenharmony_ci struct pci_dev *bridge; 338c2ecf20Sopenharmony_ci struct pci_bus *bus; 348c2ecf20Sopenharmony_ci u16 config; 358c2ecf20Sopenharmony_ci struct resource *res; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci if (is_uv_system()) 388c2ecf20Sopenharmony_ci return; 398c2ecf20Sopenharmony_ci /* Maybe, this machine supports legacy memory map. */ 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci /* Is VGA routed to us? */ 428c2ecf20Sopenharmony_ci bus = pdev->bus; 438c2ecf20Sopenharmony_ci while (bus) { 448c2ecf20Sopenharmony_ci bridge = bus->self; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci /* 478c2ecf20Sopenharmony_ci * From information provided by 488c2ecf20Sopenharmony_ci * "David Miller" <davem@davemloft.net> 498c2ecf20Sopenharmony_ci * The bridge control register is valid for PCI header 508c2ecf20Sopenharmony_ci * type BRIDGE, or CARDBUS. Host to PCI controllers use 518c2ecf20Sopenharmony_ci * PCI header type NORMAL. 528c2ecf20Sopenharmony_ci */ 538c2ecf20Sopenharmony_ci if (bridge && (pci_is_bridge(bridge))) { 548c2ecf20Sopenharmony_ci pci_read_config_word(bridge, PCI_BRIDGE_CONTROL, 558c2ecf20Sopenharmony_ci &config); 568c2ecf20Sopenharmony_ci if (!(config & PCI_BRIDGE_CTL_VGA)) 578c2ecf20Sopenharmony_ci return; 588c2ecf20Sopenharmony_ci } 598c2ecf20Sopenharmony_ci bus = bus->parent; 608c2ecf20Sopenharmony_ci } 618c2ecf20Sopenharmony_ci if (!vga_default_device() || pdev == vga_default_device()) { 628c2ecf20Sopenharmony_ci pci_read_config_word(pdev, PCI_COMMAND, &config); 638c2ecf20Sopenharmony_ci if (config & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY)) { 648c2ecf20Sopenharmony_ci res = &pdev->resource[PCI_ROM_RESOURCE]; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci pci_disable_rom(pdev); 678c2ecf20Sopenharmony_ci if (res->parent) 688c2ecf20Sopenharmony_ci release_resource(res); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci res->start = 0xC0000; 718c2ecf20Sopenharmony_ci res->end = res->start + 0x20000 - 1; 728c2ecf20Sopenharmony_ci res->flags = IORESOURCE_MEM | IORESOURCE_ROM_SHADOW | 738c2ecf20Sopenharmony_ci IORESOURCE_PCI_FIXED; 748c2ecf20Sopenharmony_ci dev_info(&pdev->dev, "Video device with shadowed ROM at %pR\n", 758c2ecf20Sopenharmony_ci res); 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci } 788c2ecf20Sopenharmony_ci} 798c2ecf20Sopenharmony_ciDECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, 808c2ecf20Sopenharmony_ci PCI_CLASS_DISPLAY_VGA, 8, pci_fixup_video); 81