1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
6 #include <linux/acpi.h>
7 #include <linux/init.h>
9 #include <linux/slab.h>
10 #include <linux/pci-acpi.h>
11 #include <linux/pci-ecam.h>
15 #include <asm/loongson.h>
17 struct pci_root_info
{
18 struct acpi_pci_root_info common
;
19 struct pci_config_window
*cfg
;
22 void pcibios_add_bus(struct pci_bus
*bus
)
24 acpi_pci_add_bus(bus
);
27 int pcibios_root_bridge_prepare(struct pci_host_bridge
*bridge
)
29 struct acpi_device
*adev
= NULL
;
30 struct device
*bus_dev
= &bridge
->bus
->dev
;
31 struct pci_config_window
*cfg
= bridge
->bus
->sysdata
;
34 adev
= to_acpi_device(cfg
->parent
);
36 ACPI_COMPANION_SET(&bridge
->dev
, adev
);
37 set_dev_node(bus_dev
, pa_to_nid(cfg
->res
.start
));
42 int acpi_pci_bus_find_domain_nr(struct pci_bus
*bus
)
44 struct pci_config_window
*cfg
= bus
->sysdata
;
45 struct acpi_device
*adev
= to_acpi_device(cfg
->parent
);
46 struct acpi_pci_root
*root
= acpi_driver_data(adev
);
51 static void acpi_release_root_info(struct acpi_pci_root_info
*ci
)
53 struct pci_root_info
*info
;
55 info
= container_of(ci
, struct pci_root_info
, common
);
56 pci_ecam_free(info
->cfg
);
61 static int acpi_prepare_root_resources(struct acpi_pci_root_info
*ci
)
64 struct resource_entry
*entry
, *tmp
;
65 struct acpi_device
*device
= ci
->bridge
;
67 status
= acpi_pci_probe_root_resources(ci
);
69 resource_list_for_each_entry_safe(entry
, tmp
, &ci
->resources
) {
70 if (entry
->res
->flags
& IORESOURCE_MEM
) {
71 entry
->offset
= ci
->root
->mcfg_addr
& GENMASK_ULL(63, 40);
72 entry
->res
->start
|= entry
->offset
;
73 entry
->res
->end
|= entry
->offset
;
79 resource_list_for_each_entry_safe(entry
, tmp
, &ci
->resources
) {
81 "host bridge window %pR (ignored)\n", entry
->res
);
82 resource_list_destroy_entry(entry
);
89 * Create a PCI config space window
90 * - reserve mem region
91 * - alloc struct pci_config_window with space for all mappings
92 * - ioremap the config space
94 static struct pci_config_window
*arch_pci_ecam_create(struct device
*dev
,
95 struct resource
*cfgres
, struct resource
*busr
, const struct pci_ecam_ops
*ops
)
97 int bsz
, bus_range
, err
;
98 struct resource
*conflict
;
99 struct pci_config_window
*cfg
;
101 if (busr
->start
> busr
->end
)
102 return ERR_PTR(-EINVAL
);
104 cfg
= kzalloc(sizeof(*cfg
), GFP_KERNEL
);
106 return ERR_PTR(-ENOMEM
);
110 cfg
->busr
.start
= busr
->start
;
111 cfg
->busr
.end
= busr
->end
;
112 cfg
->busr
.flags
= IORESOURCE_BUS
;
113 bus_range
= resource_size(cfgres
) >> ops
->bus_shift
;
115 bsz
= 1 << ops
->bus_shift
;
117 cfg
->res
.start
= cfgres
->start
;
118 cfg
->res
.end
= cfgres
->end
;
119 cfg
->res
.flags
= IORESOURCE_MEM
| IORESOURCE_BUSY
;
120 cfg
->res
.name
= "PCI ECAM";
122 conflict
= request_resource_conflict(&iomem_resource
, &cfg
->res
);
125 dev_err(dev
, "can't claim ECAM area %pR: address conflict with %s %pR\n",
126 &cfg
->res
, conflict
->name
, conflict
);
130 cfg
->win
= pci_remap_cfgspace(cfgres
->start
, bus_range
* bsz
);
135 err
= ops
->init(cfg
);
139 dev_info(dev
, "ECAM at %pR for %pR\n", &cfg
->res
, &cfg
->busr
);
145 dev_err(dev
, "ECAM ioremap failed\n");
152 * Lookup the bus range for the domain in MCFG, and set up config space
155 static struct pci_config_window
*
156 pci_acpi_setup_ecam_mapping(struct acpi_pci_root
*root
)
159 u16 seg
= root
->segment
;
160 struct device
*dev
= &root
->device
->dev
;
161 struct resource cfgres
;
162 struct resource
*bus_res
= &root
->secondary
;
163 struct pci_config_window
*cfg
;
164 const struct pci_ecam_ops
*ecam_ops
;
166 ret
= pci_mcfg_lookup(root
, &cfgres
, &ecam_ops
);
168 dev_err(dev
, "%04x:%pR ECAM region not found, use default value\n", seg
, bus_res
);
169 ecam_ops
= &loongson_pci_ecam_ops
;
170 root
->mcfg_addr
= mcfg_addr_init(0);
173 bus_shift
= ecam_ops
->bus_shift
? : 20;
176 cfg
= pci_ecam_create(dev
, &cfgres
, bus_res
, ecam_ops
);
178 cfgres
.start
= root
->mcfg_addr
+ (bus_res
->start
<< bus_shift
);
179 cfgres
.end
= cfgres
.start
+ (resource_size(bus_res
) << bus_shift
) - 1;
180 cfgres
.end
|= BIT(28) + (((PCI_CFG_SPACE_EXP_SIZE
- 1) & 0xf00) << 16);
181 cfgres
.flags
= IORESOURCE_MEM
;
182 cfg
= arch_pci_ecam_create(dev
, &cfgres
, bus_res
, ecam_ops
);
186 dev_err(dev
, "%04x:%pR error %ld mapping ECAM\n", seg
, bus_res
, PTR_ERR(cfg
));
193 struct pci_bus
*pci_acpi_scan_root(struct acpi_pci_root
*root
)
196 struct pci_root_info
*info
;
197 struct acpi_pci_root_ops
*root_ops
;
198 int domain
= root
->segment
;
199 int busnum
= root
->secondary
.start
;
201 info
= kzalloc(sizeof(*info
), GFP_KERNEL
);
203 pr_warn("pci_bus %04x:%02x: ignored (out of memory)\n", domain
, busnum
);
207 root_ops
= kzalloc(sizeof(*root_ops
), GFP_KERNEL
);
213 info
->cfg
= pci_acpi_setup_ecam_mapping(root
);
220 root_ops
->release_info
= acpi_release_root_info
;
221 root_ops
->prepare_resources
= acpi_prepare_root_resources
;
222 root_ops
->pci_ops
= (struct pci_ops
*)&info
->cfg
->ops
->pci_ops
;
224 bus
= pci_find_bus(domain
, busnum
);
226 memcpy(bus
->sysdata
, info
->cfg
, sizeof(struct pci_config_window
));
230 struct pci_bus
*child
;
232 bus
= acpi_pci_root_create(root
, root_ops
,
233 &info
->common
, info
->cfg
);
240 pci_bus_size_bridges(bus
);
241 pci_bus_assign_resources(bus
);
242 list_for_each_entry(child
, &bus
->children
, node
)
243 pcie_bus_configure_settings(child
);