39#include "opt_platform.h"
44#include <sys/kernel.h>
45#include <sys/malloc.h>
46#include <sys/module.h>
50#include <machine/intr.h>
53#include <dev/ofw/openfirm.h>
54#include <dev/ofw/ofw_bus.h>
55#include <dev/ofw/ofw_bus_subr.h>
56#include <dev/ofw/ofw_pci.h>
64#include <machine/intr.h>
68#define SPACE_CODE_SHIFT 24
69#define SPACE_CODE_MASK 0x3
70#define SPACE_CODE_IO_SPACE 0x1
71#define PROPS_CELL_SIZE 1
72#define PCI_ADDR_CELL_SIZE 2
76 struct ofw_bus_devinfo di_dinfo;
94 if (!ofw_bus_status_okay(
dev))
97 if (ofw_bus_is_compatible(
dev,
"pci-host-ecam-generic")) {
98 device_set_desc(
dev,
"Generic PCI host controller");
99 return (BUS_PROBE_GENERIC);
101 if (ofw_bus_is_compatible(
dev,
"arm,gem5_pcie")) {
102 device_set_desc(
dev,
"GEM5 PCIe host controller");
103 return (BUS_PROBE_DEFAULT);
116 sc = device_get_softc(
dev);
118 STAILQ_INIT(&sc->pci_ofw_devlist);
122 device_printf(
dev,
"parsing FDT for ECAM%d:\n", sc->
base.
ecam);
130 node = ofw_bus_get_node(
dev);
135 device_printf(
dev,
"Bus is%s cache-coherent\n",
154 if (ofw_bus_is_compatible(
dev,
"marvell,armada8k-pcie-ecam") ||
155 ofw_bus_is_compatible(
dev,
"socionext,synquacer-pcie-ecam") ||
156 ofw_bus_is_compatible(
dev,
"snps,dw-pcie-ecam")) {
157 device_set_desc(
dev,
"Synopsys DesignWare PCIe Controller");
161 ofw_bus_setup_iinfo(node, &sc->
pci_iinfo,
sizeof(cell_t));
172 sc = device_get_softc(
dev);
178 device_add_child(
dev,
"pci", -1);
179 return (bus_generic_attach(
dev));
185 pcell_t pci_addr_cells, parent_addr_cells;
186 pcell_t attributes, size_cells;
193 node = ofw_bus_get_node(
dev);
195 OF_getencprop(node,
"#address-cells", &pci_addr_cells,
196 sizeof(pci_addr_cells));
197 OF_getencprop(node,
"#size-cells", &size_cells,
199 OF_getencprop(OF_parent(node),
"#address-cells", &parent_addr_cells,
200 sizeof(parent_addr_cells));
202 if (parent_addr_cells > 2 || pci_addr_cells != 3 || size_cells > 2) {
204 "Unexpected number of address or size cells in FDT\n");
208 nbase_ranges = OF_getproplen(node,
"ranges");
209 sc->
nranges = nbase_ranges /
sizeof(cell_t) /
210 (parent_addr_cells + pci_addr_cells + size_cells);
211 base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
212 OF_getencprop(node,
"ranges", base_ranges, nbase_ranges);
214 for (i = 0, j = 0; i < sc->
nranges; i++) {
224 for (k = 0; k < (pci_addr_cells - 1); k++) {
229 for (k = 0; k < parent_addr_cells; k++) {
234 for (k = 0; k < size_cells; k++) {
250 "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
257 free(base_ranges, M_DEVBUF);
265 struct ofw_pci_register
reg;
266 uint32_t pintr, mintr[4];
270 sc = device_get_softc(
bus);
274 reg.phys_hi = (pci_get_bus(
dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
275 (pci_get_slot(
dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
276 (pci_get_function(
dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
278 intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(
dev),
280 mintr,
sizeof(mintr), &iparent);
282 pintr = ofw_bus_map_intr(
dev, iparent, intrcells, mintr);
286 device_printf(
bus,
"could not route pin %d for device %d.%d\n",
287 pin, pci_get_slot(
dev), pci_get_function(
dev));
288 return (PCI_INVALID_IRQ);
296 phandle_t msi_parent;
299 err = ofw_bus_msimap(ofw_bus_get_node(
pci), pci_get_rid(
child),
314 phandle_t msi_parent;
317 err = ofw_bus_msimap(ofw_bus_get_node(
pci), pci_get_rid(
child),
332 phandle_t msi_parent;
335 err = ofw_bus_msimap(ofw_bus_get_node(
pci), pci_get_rid(
child),
349 phandle_t msi_parent;
352 err = ofw_bus_msimap(ofw_bus_get_node(
pci), pci_get_rid(
child),
356 return (intr_alloc_msix(
pci,
child, msi_parent,
irq));
366 phandle_t msi_parent;
369 err = ofw_bus_msimap(ofw_bus_get_node(
pci), pci_get_rid(
child),
373 return (intr_release_msix(
pci,
child, msi_parent,
irq));
391 node = ofw_bus_get_node(
pci);
392 pci_rid = pci_get_rid(
child);
394 err = ofw_bus_msimap(node, pci_rid, NULL, &
rid);
402static const struct ofw_bus_devinfo *
409 sc = device_get_softc(
bus);
412 busno = pci_get_bus(
child);
414 STAILQ_FOREACH(di, &sc->pci_ofw_devlist, pci_ofw_link)
415 if (
slot == di->slot &&
func == di->func && busno == di->bus)
416 return (&di->di_dinfo);
428 phandle_t parent, node;
432 sc = device_get_softc(
dev);
433 parent = ofw_bus_get_node(
dev);
438 for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
439 len = OF_getencprop(node,
"reg",
reg,
sizeof(
reg));
440 if (len != 5 *
sizeof(pcell_t))
444 di = malloc(
sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
445 if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
449 di->func = OFW_PCI_PHYS_HI_FUNCTION(
reg[0]);
450 di->slot = OFW_PCI_PHYS_HI_DEVICE(
reg[0]);
451 di->bus = OFW_PCI_PHYS_HI_BUS(
reg[0]);
452 STAILQ_INSERT_TAIL(&sc->pci_ofw_devlist, di, pci_ofw_link);
475 DEVMETHOD(ofw_bus_get_compat, ofw_bus_gen_get_compat),
476 DEVMETHOD(ofw_bus_get_model, ofw_bus_gen_get_model),
477 DEVMETHOD(ofw_bus_get_name, ofw_bus_gen_get_name),
478 DEVMETHOD(ofw_bus_get_node, ofw_bus_gen_get_node),
479 DEVMETHOD(ofw_bus_get_type, ofw_bus_gen_get_type),
int pci_host_generic_core_release_resource(device_t dev, device_t child, int type, int rid, struct resource *res)
struct resource * pci_host_generic_core_alloc_resource(device_t dev, device_t child, int type, int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
int pci_host_generic_core_attach(device_t dev)
#define PCIE_ECAM_DESIGNWARE_QUIRK
#define MAX_RANGES_TUPLES
static int parse_pci_mem_ranges(device_t, struct generic_pcie_core_softc *)
static device_method_t generic_pcie_fdt_methods[]
static int generic_pcie_fdt_alloc_msi(device_t pci, device_t child, int count, int maxcount, int *irqs)
static devclass_t generic_pcie_fdt_devclass
DRIVER_MODULE(pcib, simplebus, generic_pcie_fdt_driver, generic_pcie_fdt_devclass, 0, 0)
#define SPACE_CODE_IO_SPACE
static int generic_pcie_fdt_alloc_msix(device_t pci, device_t child, int *irq)
static int generic_pcie_fdt_release_msix(device_t pci, device_t child, int irq)
static const struct ofw_bus_devinfo * generic_pcie_ofw_get_devinfo(device_t, device_t)
static int generic_pcie_fdt_probe(device_t dev)
static int generic_pcie_fdt_route_interrupt(device_t bus, device_t dev, int pin)
DEFINE_CLASS_1(pcib, generic_pcie_fdt_driver, generic_pcie_fdt_methods, sizeof(struct generic_pcie_fdt_softc), generic_pcie_core_driver)
int pci_host_generic_attach(device_t dev)
static int generic_pcie_fdt_map_msi(device_t pci, device_t child, int irq, uint64_t *addr, uint32_t *data)
int pci_host_generic_setup_fdt(device_t dev)
static int generic_pcie_fdt_release_msi(device_t pci, device_t child, int count, int *irqs)
static int generic_pcie_ofw_bus_attach(device_t)
int generic_pcie_get_id(device_t pci, device_t child, enum pci_id_type type, uintptr_t *id)
int pcib_alloc_msix(device_t pcib, device_t dev, int *irq)
int pcib_release_msix(device_t pcib, device_t dev, int irq)
int pcib_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
int pcib_release_msi(device_t pcib, device_t dev, int count, int *irqs)
int pcib_route_interrupt(device_t pcib, device_t dev, int pin)
int pcib_request_feature_allow(device_t pcib, device_t dev, enum pci_feature feature)
int pcib_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr, uint32_t *data)
int pcib_request_feature(device_t dev, enum pci_feature feature)
struct pcie_range ranges[MAX_RANGES_TUPLES]
struct ofw_bus_iinfo pci_iinfo
struct generic_pcie_core_softc base