1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 */ 5 #include <linux/pci.h> 6 #include <linux/acpi.h> 7 #include <linux/init.h> 8 #include <linux/irq.h> 9 #include <linux/slab.h> 10 #include <linux/pci-acpi.h> 11 #include <linux/pci-ecam.h> 12 13 #include <asm/pci.h> 14 #include <asm/numa.h> 15 #include <asm/loongson.h> 16 17 struct pci_root_info { 18 struct acpi_pci_root_info common; 19 struct pci_config_window *cfg; 20 }; 21 22 void pcibios_add_bus(struct pci_bus *bus) 23 { 24 acpi_pci_add_bus(bus); 25 } 26 27 int pcibios_root_bridge_prepare(struct pci_host_bridge *bridge) 28 { 29 struct pci_config_window *cfg = bridge->bus->sysdata; 30 struct acpi_device *adev = to_acpi_device(cfg->parent); 31 struct device *bus_dev = &bridge->bus->dev; 32 33 ACPI_COMPANION_SET(&bridge->dev, adev); 34 set_dev_node(bus_dev, pa_to_nid(cfg->res.start)); 35 36 return 0; 37 } 38 39 int acpi_pci_bus_find_domain_nr(struct pci_bus *bus) 40 { 41 struct pci_config_window *cfg = bus->sysdata; 42 struct acpi_device *adev = to_acpi_device(cfg->parent); 43 struct acpi_pci_root *root = acpi_driver_data(adev); 44 45 return root->segment; 46 } 47 48 static void acpi_release_root_info(struct acpi_pci_root_info *ci) 49 { 50 struct pci_root_info *info; 51 52 info = container_of(ci, struct pci_root_info, common); 53 pci_ecam_free(info->cfg); 54 kfree(ci->ops); 55 kfree(info); 56 } 57 58 static int acpi_prepare_root_resources(struct acpi_pci_root_info *ci) 59 { 60 int status; 61 struct resource_entry *entry, *tmp; 62 struct acpi_device *device = ci->bridge; 63 64 status = acpi_pci_probe_root_resources(ci); 65 if (status > 0) { 66 resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { 67 if (entry->res->flags & IORESOURCE_MEM) { 68 entry->offset = ci->root->mcfg_addr & GENMASK_ULL(63, 40); 69 entry->res->start |= entry->offset; 70 entry->res->end |= entry->offset; 71 } 72 } 73 return status; 74 } 75 76 resource_list_for_each_entry_safe(entry, tmp, &ci->resources) { 77 dev_dbg(&device->dev, 78 "host bridge window %pR (ignored)\n", entry->res); 79 resource_list_destroy_entry(entry); 80 } 81 82 return 0; 83 } 84 85 /* 86 * Create a PCI config space window 87 * - reserve mem region 88 * - alloc struct pci_config_window with space for all mappings 89 * - ioremap the config space 90 */ 91 static struct pci_config_window *arch_pci_ecam_create(struct device *dev, 92 struct resource *cfgres, struct resource *busr, const struct pci_ecam_ops *ops) 93 { 94 int bsz, bus_range, err; 95 struct resource *conflict; 96 struct pci_config_window *cfg; 97 98 if (busr->start > busr->end) 99 return ERR_PTR(-EINVAL); 100 101 cfg = kzalloc(sizeof(*cfg), GFP_KERNEL); 102 if (!cfg) 103 return ERR_PTR(-ENOMEM); 104 105 cfg->parent = dev; 106 cfg->ops = ops; 107 cfg->busr.start = busr->start; 108 cfg->busr.end = busr->end; 109 cfg->busr.flags = IORESOURCE_BUS; 110 bus_range = resource_size(cfgres) >> ops->bus_shift; 111 112 bsz = 1 << ops->bus_shift; 113 114 cfg->res.start = cfgres->start; 115 cfg->res.end = cfgres->end; 116 cfg->res.flags = IORESOURCE_MEM | IORESOURCE_BUSY; 117 cfg->res.name = "PCI ECAM"; 118 119 conflict = request_resource_conflict(&iomem_resource, &cfg->res); 120 if (conflict) { 121 err = -EBUSY; 122 dev_err(dev, "can't claim ECAM area %pR: address conflict with %s %pR\n", 123 &cfg->res, conflict->name, conflict); 124 goto err_exit; 125 } 126 127 cfg->win = pci_remap_cfgspace(cfgres->start, bus_range * bsz); 128 if (!cfg->win) 129 goto err_exit_iomap; 130 131 if (ops->init) { 132 err = ops->init(cfg); 133 if (err) 134 goto err_exit; 135 } 136 dev_info(dev, "ECAM at %pR for %pR\n", &cfg->res, &cfg->busr); 137 138 return cfg; 139 140 err_exit_iomap: 141 err = -ENOMEM; 142 dev_err(dev, "ECAM ioremap failed\n"); 143 err_exit: 144 pci_ecam_free(cfg); 145 return ERR_PTR(err); 146 } 147 148 /* 149 * Lookup the bus range for the domain in MCFG, and set up config space 150 * mapping. 151 */ 152 static struct pci_config_window * 153 pci_acpi_setup_ecam_mapping(struct acpi_pci_root *root) 154 { 155 int ret, bus_shift; 156 u16 seg = root->segment; 157 struct device *dev = &root->device->dev; 158 struct resource cfgres; 159 struct resource *bus_res = &root->secondary; 160 struct pci_config_window *cfg; 161 const struct pci_ecam_ops *ecam_ops; 162 163 ret = pci_mcfg_lookup(root, &cfgres, &ecam_ops); 164 if (ret < 0) { 165 dev_err(dev, "%04x:%pR ECAM region not found, use default value\n", seg, bus_res); 166 ecam_ops = &loongson_pci_ecam_ops; 167 root->mcfg_addr = mcfg_addr_init(0); 168 } 169 170 bus_shift = ecam_ops->bus_shift ? : 20; 171 172 if (bus_shift == 20) 173 cfg = pci_ecam_create(dev, &cfgres, bus_res, ecam_ops); 174 else { 175 cfgres.start = root->mcfg_addr + (bus_res->start << bus_shift); 176 cfgres.end = cfgres.start + (resource_size(bus_res) << bus_shift) - 1; 177 cfgres.end |= BIT(28) + (((PCI_CFG_SPACE_EXP_SIZE - 1) & 0xf00) << 16); 178 cfgres.flags = IORESOURCE_MEM; 179 cfg = arch_pci_ecam_create(dev, &cfgres, bus_res, ecam_ops); 180 } 181 182 if (IS_ERR(cfg)) { 183 dev_err(dev, "%04x:%pR error %ld mapping ECAM\n", seg, bus_res, PTR_ERR(cfg)); 184 return NULL; 185 } 186 187 return cfg; 188 } 189 190 struct pci_bus *pci_acpi_scan_root(struct acpi_pci_root *root) 191 { 192 struct pci_bus *bus; 193 struct pci_root_info *info; 194 struct acpi_pci_root_ops *root_ops; 195 int domain = root->segment; 196 int busnum = root->secondary.start; 197 198 info = kzalloc(sizeof(*info), GFP_KERNEL); 199 if (!info) { 200 pr_warn("pci_bus %04x:%02x: ignored (out of memory)\n", domain, busnum); 201 return NULL; 202 } 203 204 root_ops = kzalloc(sizeof(*root_ops), GFP_KERNEL); 205 if (!root_ops) { 206 kfree(info); 207 return NULL; 208 } 209 210 info->cfg = pci_acpi_setup_ecam_mapping(root); 211 if (!info->cfg) { 212 kfree(info); 213 kfree(root_ops); 214 return NULL; 215 } 216 217 root_ops->release_info = acpi_release_root_info; 218 root_ops->prepare_resources = acpi_prepare_root_resources; 219 root_ops->pci_ops = (struct pci_ops *)&info->cfg->ops->pci_ops; 220 221 bus = pci_find_bus(domain, busnum); 222 if (bus) { 223 memcpy(bus->sysdata, info->cfg, sizeof(struct pci_config_window)); 224 kfree(info); 225 } else { 226 struct pci_bus *child; 227 228 bus = acpi_pci_root_create(root, root_ops, 229 &info->common, info->cfg); 230 if (!bus) { 231 kfree(info); 232 kfree(root_ops); 233 return NULL; 234 } 235 236 pci_bus_size_bridges(bus); 237 pci_bus_assign_resources(bus); 238 list_for_each_entry(child, &bus->children, node) 239 pcie_bus_configure_settings(child); 240 } 241 242 return bus; 243 } 244