1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * Code borrowed from powerpc/kernel/pci-common.c 4 * 5 * Copyright (C) 2003 Anton Blanchard <anton@au.ibm.com>, IBM 6 * Copyright (C) 2014 ARM Ltd. 7 */ 8 9#include <linux/acpi.h> 10#include <linux/init.h> 11#include <linux/io.h> 12#include <linux/kernel.h> 13#include <linux/mm.h> 14#include <linux/pci.h> 15#include <linux/pci-acpi.h> 16#include <linux/pci-ecam.h> 17#include <linux/slab.h> 18 19#ifdef CONFIG_ACPI 20/* 21 * Try to assign the IRQ number when probing a new device 22 */ 23int pcibios_alloc_irq(struct pci_dev *dev) 24{ 25 if (!acpi_disabled) 26 acpi_pci_irq_enable(dev); 27 28 return 0; 29} 30#endif 31 32/* 33 * raw_pci_read/write - Platform-specific PCI config space access. 34 */ 35int raw_pci_read(unsigned int domain, unsigned int bus, 36 unsigned int devfn, int reg, int len, u32 *val) 37{ 38 struct pci_bus *b = pci_find_bus(domain, bus); 39 40 if (!b) 41 return PCIBIOS_DEVICE_NOT_FOUND; 42 return b->ops->read(b, devfn, reg, len, val); 43} 44 45int raw_pci_write(unsigned int domain, unsigned int bus, 46 unsigned int devfn, int reg, int len, u32 val) 47{ 48 struct pci_bus *b = pci_find_bus(domain, bus); 49 50 if (!b) 51 return PCIBIOS_DEVICE_NOT_FOUND; 52 return b->ops->write(b, devfn, reg, len, val); 53} 54 55#ifdef CONFIG_NUMA 56 57int pcibus_to_node(struct pci_bus *bus) 58{ 59 return dev_to_node(&bus->dev); 60} 61EXPORT_SYMBOL(pcibus_to_node); 62 63#endif 64 65#ifdef CONFIG_ACPI 66 67struct acpi_pci_generic_root_info { 68 struct acpi_pci_root_info common; 69 struct pci_config_window *cfg; /* config space mapping */ 70}; 71 72int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) 73{ 74 struct pci_config_window *cfg = bus->sysdata; 75 struct acpi_device *adev = to_acpi_device(cfg->parent); 76 struct acpi_pci_root *root = acpi_driver_data(adev); 77 78 return root->segment; 79} 80 81int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) 82{ 83 struct pci_config_window *cfg; 84 struct acpi_device *adev; 85 struct device *bus_dev; 86 87 if (acpi_disabled) 88 return 0; 89 90 cfg = bridge->bus->sysdata; 91 92 /* 93 * On Hyper-V there is no corresponding ACPI device for a root bridge, 94 * therefore ->parent is set as NULL by the driver. And set 'adev' as 95 * NULL in this case because there is no proper ACPI device. 96 */ 97 if (!cfg->parent) 98 adev = NULL; 99 else 100 adev = to_acpi_device(cfg->parent); 101 102 bus_dev = &bridge->bus->dev; 103 104 ACPI_COMPANION_SET(&bridge->dev, adev); 105 set_dev_node(bus_dev, acpi_get_node(acpi_device_handle(adev))); 106 107 return 0; 108} 109 110static int pci_acpi_root_prepare_resources(struct acpi_pci_root_info *ci) 111{ 112 struct resource_entry *entry, *tmp; 113 int status; 114 115 status = acpi_pci_probe_root_resources(ci); 116 resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { 117 if (!(entry->res->flags & IORESOURCE_WINDOW)) 118 resource_list_destroy_entry(entry); 119 } 120 return status; 121} 122 123/* 124 * Lookup the bus range for the domain in MCFG, and set up config space 125 * mapping. 126 */ 127static struct pci_config_window * 128pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) 129{ 130 struct device *dev = &root->device->dev; 131 struct resource *bus_res = &root->secondary; 132 u16 seg = root->segment; 133 const struct pci_ecam_ops *ecam_ops; 134 struct resource cfgres; 135 struct acpi_device *adev; 136 struct pci_config_window *cfg; 137 int ret; 138 139 ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops); 140 if (ret) { 141 dev_err(dev, "%04x:%pR ECAM region not found\n", seg, bus_res); 142 return NULL; 143 } 144 145 adev = acpi_resource_consumer(&cfgres); 146 if (adev) 147 dev_info(dev, "ECAM area %pR reserved by %s\n", &cfgres, 148 dev_name(&adev->dev)); 149 else 150 dev_warn(dev, FW_BUG "ECAM area %pR not reserved in ACPI namespace\n", 151 &cfgres); 152 153 cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops); 154 if (IS_ERR(cfg)) { 155 dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res, 156 PTR_ERR(cfg)); 157 return NULL; 158 } 159 160 return cfg; 161} 162 163/* release_info: free resources allocated by init_info */ 164static void pci_acpi_generic_release_info(struct acpi_pci_root_info *ci) 165{ 166 struct acpi_pci_generic_root_info *ri; 167 168 ri = container_of(ci, struct acpi_pci_generic_root_info, common); 169 pci_ecam_free(ri->cfg); 170 kfree(ci->ops); 171 kfree(ri); 172} 173 174/* Interface called from ACPI code to setup PCI host controller */ 175struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) 176{ 177 struct acpi_pci_generic_root_info *ri; 178 struct pci_bus *bus, *child; 179 struct acpi_pci_root_ops *root_ops; 180 struct pci_host_bridge *host; 181 182 ri = kzalloc(sizeof(*ri), GFP_KERNEL); 183 if (!ri) 184 return NULL; 185 186 root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL); 187 if (!root_ops) { 188 kfree(ri); 189 return NULL; 190 } 191 192 ri->cfg = pci_acpi_setup_ecam_mapping(root); 193 if (!ri->cfg) { 194 kfree(ri); 195 kfree(root_ops); 196 return NULL; 197 } 198 199 root_ops->release_info = pci_acpi_generic_release_info; 200 root_ops->prepare_resources = pci_acpi_root_prepare_resources; 201 root_ops->pci_ops = (struct pci_ops *)&ri->cfg->ops->pci_ops; 202 bus = acpi_pci_root_create(root, root_ops, &ri->common, ri->cfg); 203 if (!bus) 204 return NULL; 205 206 /* If we must preserve the resource configuration, claim now */ 207 host = pci_find_host_bridge(bus); 208 if (host->preserve_config) 209 pci_bus_claim_resources(bus); 210 211 /* 212 * Assign whatever was left unassigned. If we didn't claim above, 213 * this will reassign everything. 214 */ 215 pci_assign_unassigned_root_bus_resources(bus); 216 217 list_for_each_entry(child, &bus->children, node) 218 pcie_bus_configure_settings(child); 219 220 return bus; 221} 222 223void pcibios_add_bus(struct pci_bus *bus) 224{ 225 acpi_pci_add_bus(bus); 226} 227 228void pcibios_remove_bus(struct pci_bus *bus) 229{ 230 acpi_pci_remove_bus(bus); 231} 232 233#endif 234