1284317Sbr/*-
2284317Sbr * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3284317Sbr * Copyright (c) 2014 The FreeBSD Foundation
4284317Sbr * All rights reserved.
5284317Sbr *
6284317Sbr * This software was developed by Semihalf under
7284317Sbr * the sponsorship of the FreeBSD Foundation.
8284317Sbr *
9284317Sbr * Redistribution and use in source and binary forms, with or without
10284317Sbr * modification, are permitted provided that the following conditions
11284317Sbr * are met:
12284317Sbr * 1. Redistributions of source code must retain the above copyright
13284317Sbr * notice, this list of conditions and the following disclaimer.
14284317Sbr * 2. Redistributions in binary form must reproduce the above copyright
15284317Sbr * notice, this list of conditions and the following disclaimer in the
16284317Sbr * documentation and/or other materials provided with the distribution.
17284317Sbr *
18284317Sbr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19284317Sbr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20284317Sbr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21284317Sbr * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22284317Sbr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23284317Sbr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24284317Sbr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25284317Sbr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26284317Sbr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27284317Sbr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28284317Sbr * SUCH DAMAGE.
29284317Sbr */
30284317Sbr
31284317Sbr/* Generic ECAM PCIe driver */
32284317Sbr
33284317Sbr#include <sys/cdefs.h>
34284317Sbr__FBSDID("$FreeBSD: stable/11/sys/dev/pci/pci_host_generic.c 308333 2016-11-05 10:23:02Z mmel $");
35284317Sbr
36295962Swma#include "opt_platform.h"
37295962Swma
38284317Sbr#include <sys/param.h>
39284317Sbr#include <sys/systm.h>
40284317Sbr#include <sys/malloc.h>
41284317Sbr#include <sys/kernel.h>
42284317Sbr#include <sys/rman.h>
43284317Sbr#include <sys/module.h>
44284317Sbr#include <sys/bus.h>
45284317Sbr#include <sys/endian.h>
46284317Sbr#include <sys/cpuset.h>
47284317Sbr#include <sys/rwlock.h>
48292215Sandrew
49299928Sandrew#if defined(INTRNG)
50299928Sandrew#include <machine/intr.h>
51299928Sandrew#endif
52299928Sandrew
53284317Sbr#include <dev/ofw/openfirm.h>
54284317Sbr#include <dev/ofw/ofw_bus.h>
55284317Sbr#include <dev/ofw/ofw_bus_subr.h>
56292215Sandrew#include <dev/ofw/ofw_pci.h>
57284317Sbr#include <dev/pci/pcivar.h>
58284317Sbr#include <dev/pci/pcireg.h>
59284317Sbr#include <dev/pci/pcib_private.h>
60295962Swma#include <dev/pci/pci_host_generic.h>
61292215Sandrew
62284317Sbr#include <machine/cpu.h>
63284317Sbr#include <machine/bus.h>
64284317Sbr#include <machine/intr.h>
65284317Sbr#include <vm/vm_page.h>
66284317Sbr
67284317Sbr#include "pcib_if.h"
68284317Sbr
69284317Sbr/* Assembling ECAM Configuration Address */
70284317Sbr#define	PCIE_BUS_SHIFT		20
71284317Sbr#define	PCIE_SLOT_SHIFT		15
72284317Sbr#define	PCIE_FUNC_SHIFT		12
73284317Sbr#define	PCIE_BUS_MASK		0xFF
74284317Sbr#define	PCIE_SLOT_MASK		0x1F
75284317Sbr#define	PCIE_FUNC_MASK		0x07
76284317Sbr#define	PCIE_REG_MASK		0xFFF
77284317Sbr
78284317Sbr#define	PCIE_ADDR_OFFSET(bus, slot, func, reg)			\
79284317Sbr	((((bus) & PCIE_BUS_MASK) << PCIE_BUS_SHIFT)	|	\
80284317Sbr	(((slot) & PCIE_SLOT_MASK) << PCIE_SLOT_SHIFT)	|	\
81284317Sbr	(((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT)	|	\
82284317Sbr	((reg) & PCIE_REG_MASK))
83284317Sbr
84284317Sbr#define	PCI_IO_WINDOW_OFFSET	0x1000
85284317Sbr
86284317Sbr#define	SPACE_CODE_SHIFT	24
87284317Sbr#define	SPACE_CODE_MASK		0x3
88284317Sbr#define	SPACE_CODE_IO_SPACE	0x1
89284317Sbr#define	PROPS_CELL_SIZE		1
90284317Sbr#define	PCI_ADDR_CELL_SIZE	2
91284317Sbr
92295962Swma/* OFW bus interface */
93295962Swmastruct generic_pcie_ofw_devinfo {
94295962Swma	struct ofw_bus_devinfo	di_dinfo;
95295962Swma	struct resource_list	di_rl;
96284317Sbr};
97284317Sbr
98284317Sbr/* Forward prototypes */
99284317Sbr
100284317Sbrstatic int generic_pcie_probe(device_t dev);
101284317Sbrstatic int parse_pci_mem_ranges(struct generic_pcie_softc *sc);
102284317Sbrstatic uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
103284317Sbr    u_int func, u_int reg, int bytes);
104284317Sbrstatic void generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
105284317Sbr    u_int func, u_int reg, uint32_t val, int bytes);
106284317Sbrstatic int generic_pcie_maxslots(device_t dev);
107284317Sbrstatic int generic_pcie_read_ivar(device_t dev, device_t child, int index,
108284317Sbr    uintptr_t *result);
109284317Sbrstatic int generic_pcie_write_ivar(device_t dev, device_t child, int index,
110284317Sbr    uintptr_t value);
111295962Swmastatic struct resource *generic_pcie_alloc_resource_ofw(device_t, device_t,
112295962Swma    int, int *, rman_res_t, rman_res_t, rman_res_t, u_int);
113295962Swmastatic struct resource *generic_pcie_alloc_resource_pcie(device_t dev,
114295962Swma    device_t child, int type, int *rid, rman_res_t start, rman_res_t end,
115295962Swma    rman_res_t count, u_int flags);
116284317Sbrstatic int generic_pcie_release_resource(device_t dev, device_t child,
117284317Sbr    int type, int rid, struct resource *res);
118295962Swmastatic int generic_pcie_release_resource_ofw(device_t, device_t, int, int,
119295962Swma    struct resource *);
120295962Swmastatic int generic_pcie_release_resource_pcie(device_t, device_t, int, int,
121295962Swma    struct resource *);
122295962Swmastatic int generic_pcie_ofw_bus_attach(device_t);
123295962Swmastatic const struct ofw_bus_devinfo *generic_pcie_ofw_get_devinfo(device_t,
124295962Swma    device_t);
125284317Sbr
126295962Swmastatic __inline void
127295962Swmaget_addr_size_cells(phandle_t node, pcell_t *addr_cells, pcell_t *size_cells)
128295962Swma{
129295962Swma
130295962Swma	*addr_cells = 2;
131295962Swma	/* Find address cells if present */
132295962Swma	OF_getencprop(node, "#address-cells", addr_cells, sizeof(*addr_cells));
133295962Swma
134295962Swma	*size_cells = 2;
135295962Swma	/* Find size cells if present */
136295962Swma	OF_getencprop(node, "#size-cells", size_cells, sizeof(*size_cells));
137295962Swma}
138295962Swma
139284317Sbrstatic int
140284317Sbrgeneric_pcie_probe(device_t dev)
141284317Sbr{
142284317Sbr
143284317Sbr	if (!ofw_bus_status_okay(dev))
144284317Sbr		return (ENXIO);
145284317Sbr
146284317Sbr	if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic")) {
147284317Sbr		device_set_desc(dev, "Generic PCI host controller");
148295962Swma		return (BUS_PROBE_GENERIC);
149284317Sbr	}
150296316Sbz	if (ofw_bus_is_compatible(dev, "arm,gem5_pcie")) {
151296316Sbz		device_set_desc(dev, "GEM5 PCIe host controller");
152296316Sbz		return (BUS_PROBE_DEFAULT);
153296316Sbz	}
154284317Sbr
155284317Sbr	return (ENXIO);
156284317Sbr}
157284317Sbr
158295962Swmaint
159295962Swmapci_host_generic_attach(device_t dev)
160284317Sbr{
161284317Sbr	struct generic_pcie_softc *sc;
162284317Sbr	uint64_t phys_base;
163284317Sbr	uint64_t pci_base;
164284317Sbr	uint64_t size;
165299928Sandrew	phandle_t node;
166284317Sbr	int error;
167284317Sbr	int tuple;
168284317Sbr	int rid;
169284317Sbr
170284317Sbr	sc = device_get_softc(dev);
171284317Sbr	sc->dev = dev;
172284317Sbr
173295962Swma	/* Retrieve 'ranges' property from FDT */
174295962Swma	if (bootverbose)
175295962Swma		device_printf(dev, "parsing FDT for ECAM%d:\n",
176295962Swma		    sc->ecam);
177295962Swma	if (parse_pci_mem_ranges(sc))
178295962Swma		return (ENXIO);
179295962Swma
180295962Swma	/* Attach OFW bus */
181295962Swma	if (generic_pcie_ofw_bus_attach(dev) != 0)
182295962Swma		return (ENXIO);
183295962Swma
184301031Sandrew	node = ofw_bus_get_node(dev);
185301031Sandrew	if (sc->coherent == 0) {
186301031Sandrew		sc->coherent = OF_hasprop(node, "dma-coherent");
187301031Sandrew	}
188301032Sandrew	if (bootverbose)
189301031Sandrew		device_printf(dev, "Bus is%s cache-coherent\n",
190301031Sandrew		    sc->coherent ? "" : " not");
191301031Sandrew
192301031Sandrew	/* Create the parent DMA tag to pass down the coherent flag */
193301031Sandrew	error = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
194301031Sandrew	    1, 0,				/* alignment, bounds */
195301031Sandrew	    BUS_SPACE_MAXADDR,			/* lowaddr */
196301031Sandrew	    BUS_SPACE_MAXADDR,			/* highaddr */
197301031Sandrew	    NULL, NULL,				/* filter, filterarg */
198301031Sandrew	    BUS_SPACE_MAXSIZE,			/* maxsize */
199301031Sandrew	    BUS_SPACE_UNRESTRICTED,		/* nsegments */
200301031Sandrew	    BUS_SPACE_MAXSIZE,			/* maxsegsize */
201301031Sandrew	    sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
202301031Sandrew	    NULL, NULL,				/* lockfunc, lockarg */
203301031Sandrew	    &sc->dmat);
204301031Sandrew	if (error != 0)
205301031Sandrew		return (error);
206301031Sandrew
207284317Sbr	rid = 0;
208284317Sbr	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
209284317Sbr	if (sc->res == NULL) {
210284317Sbr		device_printf(dev, "could not map memory.\n");
211284317Sbr		return (ENXIO);
212284317Sbr	}
213284317Sbr
214284317Sbr	sc->bst = rman_get_bustag(sc->res);
215284317Sbr	sc->bsh = rman_get_bushandle(sc->res);
216284317Sbr
217284317Sbr	sc->mem_rman.rm_type = RMAN_ARRAY;
218284317Sbr	sc->mem_rman.rm_descr = "PCIe Memory";
219284317Sbr	sc->io_rman.rm_type = RMAN_ARRAY;
220284317Sbr	sc->io_rman.rm_descr = "PCIe IO window";
221284317Sbr
222284317Sbr	/* Initialize rman and allocate memory regions */
223284317Sbr	error = rman_init(&sc->mem_rman);
224284317Sbr	if (error) {
225284317Sbr		device_printf(dev, "rman_init() failed. error = %d\n", error);
226284317Sbr		return (error);
227284317Sbr	}
228284317Sbr
229284317Sbr	error = rman_init(&sc->io_rman);
230284317Sbr	if (error) {
231284317Sbr		device_printf(dev, "rman_init() failed. error = %d\n", error);
232284317Sbr		return (error);
233284317Sbr	}
234284317Sbr
235284317Sbr	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
236284317Sbr		phys_base = sc->ranges[tuple].phys_base;
237284317Sbr		pci_base = sc->ranges[tuple].pci_base;
238284317Sbr		size = sc->ranges[tuple].size;
239284317Sbr		if (phys_base == 0 || size == 0)
240284317Sbr			continue; /* empty range element */
241284317Sbr		if (sc->ranges[tuple].flags & FLAG_MEM) {
242284317Sbr			error = rman_manage_region(&sc->mem_rman,
243296316Sbz			   phys_base, phys_base + size - 1);
244284317Sbr		} else if (sc->ranges[tuple].flags & FLAG_IO) {
245284317Sbr			error = rman_manage_region(&sc->io_rman,
246296316Sbz			   pci_base + PCI_IO_WINDOW_OFFSET,
247296316Sbz			   pci_base + PCI_IO_WINDOW_OFFSET + size - 1);
248284317Sbr		} else
249284317Sbr			continue;
250284317Sbr		if (error) {
251284317Sbr			device_printf(dev, "rman_manage_region() failed."
252284317Sbr						"error = %d\n", error);
253284317Sbr			rman_fini(&sc->mem_rman);
254284317Sbr			return (error);
255284317Sbr		}
256284317Sbr	}
257284317Sbr
258299928Sandrew	ofw_bus_setup_iinfo(node, &sc->pci_iinfo, sizeof(cell_t));
259284317Sbr
260284317Sbr	device_add_child(dev, "pci", -1);
261284317Sbr	return (bus_generic_attach(dev));
262284317Sbr}
263284317Sbr
264284317Sbrstatic int
265284317Sbrparse_pci_mem_ranges(struct generic_pcie_softc *sc)
266284317Sbr{
267284317Sbr	pcell_t pci_addr_cells, parent_addr_cells;
268284317Sbr	pcell_t attributes, size_cells;
269284317Sbr	cell_t *base_ranges;
270284317Sbr	int nbase_ranges;
271284317Sbr	phandle_t node;
272284317Sbr	int i, j, k;
273284317Sbr	int tuple;
274284317Sbr
275284317Sbr	node = ofw_bus_get_node(sc->dev);
276284317Sbr
277284317Sbr	OF_getencprop(node, "#address-cells", &pci_addr_cells,
278284317Sbr					sizeof(pci_addr_cells));
279284317Sbr	OF_getencprop(node, "#size-cells", &size_cells,
280284317Sbr					sizeof(size_cells));
281284317Sbr	OF_getencprop(OF_parent(node), "#address-cells", &parent_addr_cells,
282284317Sbr					sizeof(parent_addr_cells));
283284317Sbr
284284317Sbr	if (parent_addr_cells != 2 || pci_addr_cells != 3 || size_cells != 2) {
285284317Sbr		device_printf(sc->dev,
286284317Sbr		    "Unexpected number of address or size cells in FDT\n");
287284317Sbr		return (ENXIO);
288284317Sbr	}
289284317Sbr
290284317Sbr	nbase_ranges = OF_getproplen(node, "ranges");
291284317Sbr	sc->nranges = nbase_ranges / sizeof(cell_t) /
292284317Sbr	    (parent_addr_cells + pci_addr_cells + size_cells);
293284317Sbr	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
294284317Sbr	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
295284317Sbr
296284317Sbr	for (i = 0, j = 0; i < sc->nranges; i++) {
297284317Sbr		attributes = (base_ranges[j++] >> SPACE_CODE_SHIFT) & \
298284317Sbr							SPACE_CODE_MASK;
299284317Sbr		if (attributes == SPACE_CODE_IO_SPACE) {
300284317Sbr			sc->ranges[i].flags |= FLAG_IO;
301284317Sbr		} else {
302284317Sbr			sc->ranges[i].flags |= FLAG_MEM;
303284317Sbr		}
304284317Sbr
305284317Sbr		sc->ranges[i].pci_base = 0;
306284317Sbr		for (k = 0; k < (pci_addr_cells - 1); k++) {
307284317Sbr			sc->ranges[i].pci_base <<= 32;
308284317Sbr			sc->ranges[i].pci_base |= base_ranges[j++];
309284317Sbr		}
310284317Sbr		sc->ranges[i].phys_base = 0;
311284317Sbr		for (k = 0; k < parent_addr_cells; k++) {
312284317Sbr			sc->ranges[i].phys_base <<= 32;
313284317Sbr			sc->ranges[i].phys_base |= base_ranges[j++];
314284317Sbr		}
315284317Sbr		sc->ranges[i].size = 0;
316284317Sbr		for (k = 0; k < size_cells; k++) {
317284317Sbr			sc->ranges[i].size <<= 32;
318284317Sbr			sc->ranges[i].size |= base_ranges[j++];
319284317Sbr		}
320284317Sbr	}
321284317Sbr
322284317Sbr	for (; i < MAX_RANGES_TUPLES; i++) {
323284317Sbr		/* zero-fill remaining tuples to mark empty elements in array */
324284317Sbr		sc->ranges[i].pci_base = 0;
325284317Sbr		sc->ranges[i].phys_base = 0;
326284317Sbr		sc->ranges[i].size = 0;
327284317Sbr	}
328284317Sbr
329284317Sbr	if (bootverbose) {
330284317Sbr		for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
331284317Sbr			device_printf(sc->dev,
332284317Sbr			    "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
333284317Sbr			    sc->ranges[tuple].pci_base,
334284317Sbr			    sc->ranges[tuple].phys_base,
335284317Sbr			    sc->ranges[tuple].size);
336284317Sbr		}
337284317Sbr	}
338284317Sbr
339284317Sbr	free(base_ranges, M_DEVBUF);
340284317Sbr	return (0);
341284317Sbr}
342284317Sbr
343284317Sbrstatic uint32_t
344284317Sbrgeneric_pcie_read_config(device_t dev, u_int bus, u_int slot,
345284317Sbr    u_int func, u_int reg, int bytes)
346284317Sbr{
347284317Sbr	struct generic_pcie_softc *sc;
348284317Sbr	bus_space_handle_t h;
349284317Sbr	bus_space_tag_t	t;
350284317Sbr	uint64_t offset;
351284317Sbr	uint32_t data;
352284317Sbr
353295962Swma	if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
354295962Swma	    (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
355284317Sbr		return (~0U);
356284317Sbr
357284317Sbr	sc = device_get_softc(dev);
358284317Sbr
359284317Sbr	offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
360284317Sbr	t = sc->bst;
361284317Sbr	h = sc->bsh;
362284317Sbr
363284317Sbr	switch (bytes) {
364284317Sbr	case 1:
365284317Sbr		data = bus_space_read_1(t, h, offset);
366284317Sbr		break;
367284317Sbr	case 2:
368284317Sbr		data = le16toh(bus_space_read_2(t, h, offset));
369284317Sbr		break;
370284317Sbr	case 4:
371284317Sbr		data = le32toh(bus_space_read_4(t, h, offset));
372284317Sbr		break;
373284317Sbr	default:
374284317Sbr		return (~0U);
375284317Sbr	}
376284317Sbr
377284317Sbr	return (data);
378284317Sbr}
379284317Sbr
380284317Sbrstatic void
381284317Sbrgeneric_pcie_write_config(device_t dev, u_int bus, u_int slot,
382284317Sbr    u_int func, u_int reg, uint32_t val, int bytes)
383284317Sbr{
384284317Sbr	struct generic_pcie_softc *sc;
385284317Sbr	bus_space_handle_t h;
386284317Sbr	bus_space_tag_t t;
387284317Sbr	uint64_t offset;
388284317Sbr
389295962Swma	if ((bus > PCI_BUSMAX) || (slot > PCI_SLOTMAX) ||
390295962Swma	    (func > PCI_FUNCMAX) || (reg > PCIE_REGMAX))
391284317Sbr		return;
392284317Sbr
393284317Sbr	sc = device_get_softc(dev);
394284317Sbr
395284317Sbr	offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
396284317Sbr
397284317Sbr	t = sc->bst;
398284317Sbr	h = sc->bsh;
399284317Sbr
400284317Sbr	switch (bytes) {
401284317Sbr	case 1:
402284317Sbr		bus_space_write_1(t, h, offset, val);
403284317Sbr		break;
404284317Sbr	case 2:
405284317Sbr		bus_space_write_2(t, h, offset, htole16(val));
406284317Sbr		break;
407284317Sbr	case 4:
408284317Sbr		bus_space_write_4(t, h, offset, htole32(val));
409284317Sbr		break;
410284317Sbr	default:
411284317Sbr		return;
412284317Sbr	}
413284317Sbr}
414284317Sbr
415284317Sbrstatic int
416284317Sbrgeneric_pcie_maxslots(device_t dev)
417284317Sbr{
418284317Sbr
419284317Sbr	return (31); /* max slots per bus acc. to standard */
420284317Sbr}
421284317Sbr
422284317Sbrstatic int
423292215Sandrewgeneric_pcie_route_interrupt(device_t bus, device_t dev, int pin)
424292215Sandrew{
425292215Sandrew	struct generic_pcie_softc *sc;
426292215Sandrew	struct ofw_pci_register reg;
427292215Sandrew	uint32_t pintr, mintr[2];
428292215Sandrew	phandle_t iparent;
429292215Sandrew	int intrcells;
430292215Sandrew
431292215Sandrew	sc = device_get_softc(bus);
432292215Sandrew	pintr = pin;
433292215Sandrew
434292215Sandrew	bzero(&reg, sizeof(reg));
435292215Sandrew	reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
436292215Sandrew	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
437292215Sandrew	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
438292215Sandrew
439292215Sandrew	intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
440292215Sandrew	    &sc->pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
441292215Sandrew	    mintr, sizeof(mintr), &iparent);
442292215Sandrew	if (intrcells) {
443292215Sandrew		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
444292215Sandrew		return (pintr);
445292215Sandrew	}
446292215Sandrew
447292215Sandrew	device_printf(bus, "could not route pin %d for device %d.%d\n",
448292215Sandrew	    pin, pci_get_slot(dev), pci_get_function(dev));
449292215Sandrew	return (PCI_INVALID_IRQ);
450292215Sandrew}
451292215Sandrew
452292215Sandrew
453292215Sandrewstatic int
454284317Sbrgeneric_pcie_read_ivar(device_t dev, device_t child, int index,
455284317Sbr    uintptr_t *result)
456284317Sbr{
457284317Sbr	struct generic_pcie_softc *sc;
458284317Sbr	int secondary_bus;
459284317Sbr
460284317Sbr	sc = device_get_softc(dev);
461284317Sbr
462284317Sbr	if (index == PCIB_IVAR_BUS) {
463284317Sbr		/* this pcib adds only pci bus 0 as child */
464284317Sbr		secondary_bus = 0;
465284317Sbr		*result = secondary_bus;
466284317Sbr		return (0);
467284317Sbr
468284317Sbr	}
469284317Sbr
470284317Sbr	if (index == PCIB_IVAR_DOMAIN) {
471284317Sbr		*result = sc->ecam;
472284317Sbr		return (0);
473284317Sbr	}
474284317Sbr
475295962Swma	if (bootverbose)
476295962Swma		device_printf(dev, "ERROR: Unknown index %d.\n", index);
477284317Sbr	return (ENOENT);
478284317Sbr}
479284317Sbr
480284317Sbrstatic int
481284317Sbrgeneric_pcie_write_ivar(device_t dev, device_t child, int index,
482284317Sbr    uintptr_t value)
483284317Sbr{
484284317Sbr
485284317Sbr	return (ENOENT);
486284317Sbr}
487284317Sbr
488284317Sbrstatic struct rman *
489284317Sbrgeneric_pcie_rman(struct generic_pcie_softc *sc, int type)
490284317Sbr{
491284317Sbr
492284317Sbr	switch (type) {
493284317Sbr	case SYS_RES_IOPORT:
494284317Sbr		return (&sc->io_rman);
495284317Sbr	case SYS_RES_MEMORY:
496284317Sbr		return (&sc->mem_rman);
497284317Sbr	default:
498284317Sbr		break;
499284317Sbr	}
500284317Sbr
501284317Sbr	return (NULL);
502284317Sbr}
503284317Sbr
504284317Sbrstatic int
505295962Swmageneric_pcie_release_resource_pcie(device_t dev, device_t child, int type,
506284317Sbr    int rid, struct resource *res)
507284317Sbr{
508284317Sbr	struct generic_pcie_softc *sc;
509284317Sbr	struct rman *rm;
510284317Sbr
511284317Sbr	sc = device_get_softc(dev);
512284317Sbr
513284317Sbr	rm = generic_pcie_rman(sc, type);
514284317Sbr	if (rm != NULL) {
515284317Sbr		KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
516284317Sbr		rman_release_resource(res);
517284317Sbr	}
518284317Sbr
519284317Sbr	return (bus_generic_release_resource(dev, child, type, rid, res));
520284317Sbr}
521284317Sbr
522295962Swmastatic int
523295962Swmageneric_pcie_release_resource(device_t dev, device_t child, int type,
524295962Swma    int rid, struct resource *res)
525295962Swma{
526300290Sandrew#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
527300290Sandrew	struct generic_pcie_softc *sc;
528295962Swma
529300290Sandrew	if (type == PCI_RES_BUS) {
530300290Sandrew		sc = device_get_softc(dev);
531300290Sandrew		return (pci_domain_release_bus(sc->ecam, child, rid, res));
532300290Sandrew	}
533300290Sandrew#endif
534295962Swma	/* For PCIe devices that do not have FDT nodes, use PCIB method */
535295962Swma	if ((int)ofw_bus_get_node(child) <= 0) {
536295962Swma		return (generic_pcie_release_resource_pcie(dev,
537295962Swma		    child, type, rid, res));
538295962Swma	}
539295962Swma
540295962Swma	/* For other devices use OFW method */
541295962Swma	return (generic_pcie_release_resource_ofw(dev,
542295962Swma	    child, type, rid, res));
543295962Swma}
544295962Swma
545296091Swmastruct resource *
546296091Swmapci_host_generic_alloc_resource(device_t dev, device_t child, int type, int *rid,
547294883Sjhibbits    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
548284317Sbr{
549300290Sandrew#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
550300290Sandrew	struct generic_pcie_softc *sc;
551295962Swma
552300290Sandrew	if (type == PCI_RES_BUS) {
553300290Sandrew		sc = device_get_softc(dev);
554300290Sandrew		return (pci_domain_alloc_bus(sc->ecam, child, rid, start, end,
555300290Sandrew		    count, flags));
556300290Sandrew	}
557300290Sandrew#endif
558295962Swma	/* For PCIe devices that do not have FDT nodes, use PCIB method */
559295962Swma	if ((int)ofw_bus_get_node(child) <= 0)
560295962Swma		return (generic_pcie_alloc_resource_pcie(dev, child, type, rid,
561295962Swma		    start, end, count, flags));
562295962Swma
563295962Swma	/* For other devices use OFW method */
564295962Swma	return (generic_pcie_alloc_resource_ofw(dev, child, type, rid,
565295962Swma	    start, end, count, flags));
566295962Swma}
567295962Swma
568295962Swmastatic struct resource *
569295962Swmageneric_pcie_alloc_resource_pcie(device_t dev, device_t child, int type, int *rid,
570295962Swma    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
571295962Swma{
572284317Sbr	struct generic_pcie_softc *sc;
573284317Sbr	struct resource *res;
574284317Sbr	struct rman *rm;
575284317Sbr
576284317Sbr	sc = device_get_softc(dev);
577284317Sbr
578284317Sbr	rm = generic_pcie_rman(sc, type);
579284317Sbr	if (rm == NULL)
580284317Sbr		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
581284317Sbr		    type, rid, start, end, count, flags));
582284317Sbr
583284317Sbr	if (bootverbose) {
584284317Sbr		device_printf(dev,
585297038Sbz		    "rman_reserve_resource: start=%#jx, end=%#jx, count=%#jx\n",
586284317Sbr		    start, end, count);
587284317Sbr	}
588284317Sbr
589284317Sbr	res = rman_reserve_resource(rm, start, end, count, flags, child);
590284317Sbr	if (res == NULL)
591284317Sbr		goto fail;
592284317Sbr
593284317Sbr	rman_set_rid(res, *rid);
594284317Sbr
595284317Sbr	if (flags & RF_ACTIVE)
596284317Sbr		if (bus_activate_resource(child, type, *rid, res)) {
597284317Sbr			rman_release_resource(res);
598284317Sbr			goto fail;
599284317Sbr		}
600284317Sbr
601284317Sbr	return (res);
602284317Sbr
603284317Sbrfail:
604295962Swma	device_printf(dev, "%s FAIL: type=%d, rid=%d, "
605297038Sbz	    "start=%016jx, end=%016jx, count=%016jx, flags=%x\n",
606295962Swma	    __func__, type, *rid, start, end, count, flags);
607284317Sbr
608284317Sbr	return (NULL);
609284317Sbr}
610284317Sbr
611284317Sbrstatic int
612284317Sbrgeneric_pcie_adjust_resource(device_t dev, device_t child, int type,
613294883Sjhibbits    struct resource *res, rman_res_t start, rman_res_t end)
614284317Sbr{
615284317Sbr	struct generic_pcie_softc *sc;
616284317Sbr	struct rman *rm;
617284317Sbr
618284317Sbr	sc = device_get_softc(dev);
619300290Sandrew#if defined(NEW_PCIB) && defined(PCI_RES_BUS)
620300290Sandrew	if (type == PCI_RES_BUS)
621300290Sandrew		return (pci_domain_adjust_bus(sc->ecam, child, res, start,
622300290Sandrew		    end));
623300290Sandrew#endif
624284317Sbr
625284317Sbr	rm = generic_pcie_rman(sc, type);
626284317Sbr	if (rm != NULL)
627284317Sbr		return (rman_adjust_resource(res, start, end));
628284317Sbr	return (bus_generic_adjust_resource(dev, child, type, res, start, end));
629284317Sbr}
630284317Sbr
631284317Sbrstatic int
632284317Sbrgeneric_pcie_activate_resource(device_t dev, device_t child, int type, int rid,
633284317Sbr    struct resource *r)
634284317Sbr{
635284317Sbr	struct generic_pcie_softc *sc;
636284317Sbr	uint64_t phys_base;
637284317Sbr	uint64_t pci_base;
638284317Sbr	uint64_t size;
639284317Sbr	int found;
640284317Sbr	int res;
641284317Sbr	int i;
642284317Sbr
643284317Sbr	sc = device_get_softc(dev);
644284317Sbr
645284317Sbr	if ((res = rman_activate_resource(r)) != 0)
646284317Sbr		return (res);
647284317Sbr
648284317Sbr	switch(type) {
649284317Sbr	case SYS_RES_IOPORT:
650284317Sbr		found = 0;
651284317Sbr		for (i = 0; i < MAX_RANGES_TUPLES; i++) {
652284317Sbr			pci_base = sc->ranges[i].pci_base;
653284317Sbr			phys_base = sc->ranges[i].phys_base;
654284317Sbr			size = sc->ranges[i].size;
655284317Sbr
656284317Sbr			if ((rid > pci_base) && (rid < (pci_base + size))) {
657284317Sbr				found = 1;
658284317Sbr				break;
659284317Sbr			}
660284317Sbr		}
661284317Sbr		if (found) {
662284317Sbr			rman_set_start(r, rman_get_start(r) + phys_base);
663299658Sbz			rman_set_end(r, rman_get_end(r) + phys_base);
664284317Sbr			BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child,
665284317Sbr						type, rid, r);
666284317Sbr		} else {
667284317Sbr			device_printf(dev, "Failed to activate IOPORT resource\n");
668284317Sbr			res = 0;
669284317Sbr		}
670284317Sbr		break;
671284317Sbr	case SYS_RES_MEMORY:
672284317Sbr		BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r);
673284317Sbr		break;
674284317Sbr	default:
675284317Sbr		break;
676284317Sbr	}
677284317Sbr
678284317Sbr	return (res);
679284317Sbr}
680284317Sbr
681284317Sbrstatic int
682284317Sbrgeneric_pcie_deactivate_resource(device_t dev, device_t child, int type, int rid,
683284317Sbr    struct resource *r)
684284317Sbr{
685284317Sbr	struct generic_pcie_softc *sc;
686284317Sbr	vm_offset_t vaddr;
687284317Sbr	int res;
688284317Sbr
689284317Sbr	sc = device_get_softc(dev);
690284317Sbr
691284317Sbr	if ((res = rman_deactivate_resource(r)) != 0)
692284317Sbr		return (res);
693284317Sbr
694284317Sbr	switch(type) {
695284317Sbr	case SYS_RES_IOPORT:
696284317Sbr	case SYS_RES_MEMORY:
697284317Sbr		vaddr = (vm_offset_t)rman_get_virtual(r);
698284317Sbr		pmap_unmapdev(vaddr, rman_get_size(r));
699284317Sbr		break;
700284317Sbr	default:
701284317Sbr		break;
702284317Sbr	}
703284317Sbr
704284317Sbr	return (res);
705284317Sbr}
706284317Sbr
707301031Sandrewstatic bus_dma_tag_t
708301031Sandrewgeneric_pcie_get_dma_tag(device_t dev, device_t child)
709301031Sandrew{
710301031Sandrew	struct generic_pcie_softc *sc;
711301031Sandrew
712301031Sandrew	sc = device_get_softc(dev);
713301031Sandrew	return (sc->dmat);
714301031Sandrew}
715301031Sandrew
716298202Sandrewstatic int
717298202Sandrewgeneric_pcie_alloc_msi(device_t pci, device_t child, int count, int maxcount,
718298202Sandrew    int *irqs)
719298202Sandrew{
720299928Sandrew#if defined(INTRNG)
721299941Sandrew	phandle_t msi_parent;
722298202Sandrew
723299941Sandrew	ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
724299941Sandrew	    NULL);
725299941Sandrew	return (intr_alloc_msi(pci, child, msi_parent, count, maxcount,
726299928Sandrew	    irqs));
727298202Sandrew#else
728298202Sandrew	return (ENXIO);
729298202Sandrew#endif
730298202Sandrew}
731298202Sandrew
732298202Sandrewstatic int
733298202Sandrewgeneric_pcie_release_msi(device_t pci, device_t child, int count, int *irqs)
734298202Sandrew{
735299928Sandrew#if defined(INTRNG)
736299941Sandrew	phandle_t msi_parent;
737298202Sandrew
738299941Sandrew	ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
739299941Sandrew	    NULL);
740299941Sandrew	return (intr_release_msi(pci, child, msi_parent, count, irqs));
741298202Sandrew#else
742298202Sandrew	return (ENXIO);
743298202Sandrew#endif
744298202Sandrew}
745298202Sandrew
746298202Sandrewstatic int
747298202Sandrewgeneric_pcie_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
748298202Sandrew    uint32_t *data)
749298202Sandrew{
750299928Sandrew#if defined(INTRNG)
751299941Sandrew	phandle_t msi_parent;
752298202Sandrew
753299941Sandrew	ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
754299941Sandrew	    NULL);
755299941Sandrew	return (intr_map_msi(pci, child, msi_parent, irq, addr, data));
756298202Sandrew#else
757298202Sandrew	return (ENXIO);
758298202Sandrew#endif
759298202Sandrew}
760298202Sandrew
761298202Sandrewstatic int
762298202Sandrewgeneric_pcie_alloc_msix(device_t pci, device_t child, int *irq)
763298202Sandrew{
764299928Sandrew#if defined(INTRNG)
765299941Sandrew	phandle_t msi_parent;
766298202Sandrew
767299941Sandrew	ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
768299941Sandrew	    NULL);
769299941Sandrew	return (intr_alloc_msix(pci, child, msi_parent, irq));
770298202Sandrew#else
771298202Sandrew	return (ENXIO);
772298202Sandrew#endif
773298202Sandrew}
774298202Sandrew
775298202Sandrewstatic int
776298202Sandrewgeneric_pcie_release_msix(device_t pci, device_t child, int irq)
777298202Sandrew{
778299928Sandrew#if defined(INTRNG)
779299941Sandrew	phandle_t msi_parent;
780298202Sandrew
781299941Sandrew	ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
782299941Sandrew	    NULL);
783299941Sandrew	return (intr_release_msix(pci, child, msi_parent, irq));
784298202Sandrew#else
785298202Sandrew	return (ENXIO);
786298202Sandrew#endif
787298202Sandrew}
788298202Sandrew
789299932Sandrewint
790299932Sandrewgeneric_pcie_get_id(device_t pci, device_t child, enum pci_id_type type,
791299932Sandrew    uintptr_t *id)
792299932Sandrew{
793299932Sandrew	phandle_t node;
794299932Sandrew	uint32_t rid;
795299932Sandrew	uint16_t pci_rid;
796299932Sandrew
797299932Sandrew	if (type != PCI_ID_MSI)
798299932Sandrew		return (pcib_get_id(pci, child, type, id));
799299932Sandrew
800299932Sandrew	node = ofw_bus_get_node(pci);
801299932Sandrew	pci_rid = pci_get_rid(child);
802299932Sandrew
803299932Sandrew	ofw_bus_msimap(node, pci_rid, NULL, &rid);
804299932Sandrew	*id = rid;
805299932Sandrew
806299932Sandrew	return (0);
807299932Sandrew}
808299932Sandrew
809284317Sbrstatic device_method_t generic_pcie_methods[] = {
810284317Sbr	DEVMETHOD(device_probe,			generic_pcie_probe),
811295962Swma	DEVMETHOD(device_attach,		pci_host_generic_attach),
812284317Sbr	DEVMETHOD(bus_read_ivar,		generic_pcie_read_ivar),
813284317Sbr	DEVMETHOD(bus_write_ivar,		generic_pcie_write_ivar),
814296091Swma	DEVMETHOD(bus_alloc_resource,		pci_host_generic_alloc_resource),
815284317Sbr	DEVMETHOD(bus_adjust_resource,		generic_pcie_adjust_resource),
816284317Sbr	DEVMETHOD(bus_release_resource,		generic_pcie_release_resource),
817284317Sbr	DEVMETHOD(bus_activate_resource,	generic_pcie_activate_resource),
818284317Sbr	DEVMETHOD(bus_deactivate_resource,	generic_pcie_deactivate_resource),
819284317Sbr	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
820284317Sbr	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
821292215Sandrew
822301031Sandrew	DEVMETHOD(bus_get_dma_tag,		generic_pcie_get_dma_tag),
823301031Sandrew
824292215Sandrew	/* pcib interface */
825284317Sbr	DEVMETHOD(pcib_maxslots,		generic_pcie_maxslots),
826292215Sandrew	DEVMETHOD(pcib_route_interrupt,		generic_pcie_route_interrupt),
827284317Sbr	DEVMETHOD(pcib_read_config,		generic_pcie_read_config),
828284317Sbr	DEVMETHOD(pcib_write_config,		generic_pcie_write_config),
829298202Sandrew	DEVMETHOD(pcib_alloc_msi,		generic_pcie_alloc_msi),
830298202Sandrew	DEVMETHOD(pcib_release_msi,		generic_pcie_release_msi),
831298202Sandrew	DEVMETHOD(pcib_alloc_msix,		generic_pcie_alloc_msix),
832298202Sandrew	DEVMETHOD(pcib_release_msix,		generic_pcie_release_msix),
833298202Sandrew	DEVMETHOD(pcib_map_msi,			generic_pcie_map_msi),
834299932Sandrew	DEVMETHOD(pcib_get_id,			generic_pcie_get_id),
835292215Sandrew
836295962Swma	/* ofw_bus interface */
837295962Swma	DEVMETHOD(ofw_bus_get_devinfo,		generic_pcie_ofw_get_devinfo),
838295962Swma	DEVMETHOD(ofw_bus_get_compat,		ofw_bus_gen_get_compat),
839295962Swma	DEVMETHOD(ofw_bus_get_model,		ofw_bus_gen_get_model),
840295962Swma	DEVMETHOD(ofw_bus_get_name,		ofw_bus_gen_get_name),
841295962Swma	DEVMETHOD(ofw_bus_get_node,		ofw_bus_gen_get_node),
842295962Swma	DEVMETHOD(ofw_bus_get_type,		ofw_bus_gen_get_type),
843295962Swma
844284317Sbr	DEVMETHOD_END
845284317Sbr};
846284317Sbr
847295962Swmastatic const struct ofw_bus_devinfo *
848295962Swmageneric_pcie_ofw_get_devinfo(device_t bus __unused, device_t child)
849295962Swma{
850295962Swma	struct generic_pcie_ofw_devinfo *di;
851284317Sbr
852295962Swma	di = device_get_ivars(child);
853295962Swma	return (&di->di_dinfo);
854295962Swma}
855284317Sbr
856295962Swmastatic struct resource *
857295962Swmageneric_pcie_alloc_resource_ofw(device_t bus, device_t child, int type, int *rid,
858295962Swma    rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
859295962Swma{
860295962Swma	struct generic_pcie_softc *sc;
861295962Swma	struct generic_pcie_ofw_devinfo *di;
862295962Swma	struct resource_list_entry *rle;
863295962Swma	int i;
864295962Swma
865295962Swma	sc = device_get_softc(bus);
866295962Swma
867296298Sjhibbits	if (RMAN_IS_DEFAULT_RANGE(start, end)) {
868295962Swma		if ((di = device_get_ivars(child)) == NULL)
869295962Swma			return (NULL);
870295962Swma		if (type == SYS_RES_IOPORT)
871295962Swma		    type = SYS_RES_MEMORY;
872295962Swma
873295962Swma		/* Find defaults for this rid */
874295962Swma		rle = resource_list_find(&di->di_rl, type, *rid);
875295962Swma		if (rle == NULL)
876295962Swma			return (NULL);
877295962Swma
878295962Swma		start = rle->start;
879295962Swma		end = rle->end;
880295962Swma		count = rle->count;
881295962Swma	}
882295962Swma
883295962Swma	if (type == SYS_RES_MEMORY) {
884295962Swma		/* Remap through ranges property */
885295962Swma		for (i = 0; i < MAX_RANGES_TUPLES; i++) {
886295962Swma			if (start >= sc->ranges[i].phys_base && end <
887295962Swma			    sc->ranges[i].pci_base + sc->ranges[i].size) {
888295962Swma				start -= sc->ranges[i].phys_base;
889295962Swma				start += sc->ranges[i].pci_base;
890295962Swma				end -= sc->ranges[i].phys_base;
891295962Swma				end += sc->ranges[i].pci_base;
892295962Swma				break;
893295962Swma			}
894295962Swma		}
895295962Swma
896295962Swma		if (i == MAX_RANGES_TUPLES) {
897295962Swma			device_printf(bus, "Could not map resource "
898297038Sbz			    "%#jx-%#jx\n", start, end);
899295962Swma			return (NULL);
900295962Swma		}
901295962Swma	}
902295962Swma
903295962Swma	return (bus_generic_alloc_resource(bus, child, type, rid, start, end,
904295962Swma	    count, flags));
905295962Swma}
906295962Swma
907295962Swmastatic int
908295962Swmageneric_pcie_release_resource_ofw(device_t bus, device_t child, int type, int rid,
909295962Swma    struct resource *res)
910295962Swma{
911295962Swma
912295962Swma	return (bus_generic_release_resource(bus, child, type, rid, res));
913295962Swma}
914295962Swma
915295962Swma/* Helper functions */
916295962Swma
917295962Swmastatic int
918295962Swmageneric_pcie_ofw_bus_attach(device_t dev)
919295962Swma{
920295962Swma	struct generic_pcie_ofw_devinfo *di;
921295962Swma	device_t child;
922295962Swma	phandle_t parent, node;
923295962Swma	pcell_t addr_cells, size_cells;
924295962Swma
925295962Swma	parent = ofw_bus_get_node(dev);
926295962Swma	if (parent > 0) {
927295962Swma		get_addr_size_cells(parent, &addr_cells, &size_cells);
928295962Swma		/* Iterate through all bus subordinates */
929295962Swma		for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
930295962Swma
931295962Swma			/* Allocate and populate devinfo. */
932295962Swma			di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
933295962Swma			if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
934295962Swma				free(di, M_DEVBUF);
935295962Swma				continue;
936295962Swma			}
937295962Swma
938295962Swma			/* Initialize and populate resource list. */
939295962Swma			resource_list_init(&di->di_rl);
940295962Swma			ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
941295962Swma			    &di->di_rl);
942295962Swma			ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
943295962Swma
944295962Swma			/* Add newbus device for this FDT node */
945295962Swma			child = device_add_child(dev, NULL, -1);
946295962Swma			if (child == NULL) {
947295962Swma				resource_list_free(&di->di_rl);
948295962Swma				ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
949295962Swma				free(di, M_DEVBUF);
950295962Swma				continue;
951295962Swma			}
952295962Swma
953295962Swma			device_set_ivars(child, di);
954295962Swma		}
955295962Swma	}
956295962Swma
957295962Swma	return (0);
958295962Swma}
959295962Swma
960295962SwmaDEFINE_CLASS_0(pcib, generic_pcie_driver,
961295962Swma    generic_pcie_methods, sizeof(struct generic_pcie_softc));
962295962Swma
963295962Swmadevclass_t generic_pcie_devclass;
964295962Swma
965284317SbrDRIVER_MODULE(pcib, simplebus, generic_pcie_driver,
966295962Swma    generic_pcie_devclass, 0, 0);
967284317SbrDRIVER_MODULE(pcib, ofwbus, generic_pcie_driver,
968295962Swma    generic_pcie_devclass, 0, 0);
969295962Swma
970