xref: /freebsd/sys/dev/pci/pci_host_generic.c (revision 1f4bcc459a76b7aa664f3fd557684cd0ba6da352)
1 /*-
2  * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3  * Copyright (c) 2014 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Semihalf under
7  * the sponsorship of the FreeBSD Foundation.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28  * SUCH DAMAGE.
29  */
30 
31 /* Generic ECAM PCIe driver */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/malloc.h>
39 #include <sys/kernel.h>
40 #include <sys/rman.h>
41 #include <sys/module.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 #include <sys/cpuset.h>
45 #include <sys/rwlock.h>
46 
47 #include <dev/ofw/openfirm.h>
48 #include <dev/ofw/ofw_bus.h>
49 #include <dev/ofw/ofw_bus_subr.h>
50 #include <dev/ofw/ofw_pci.h>
51 #include <dev/pci/pcivar.h>
52 #include <dev/pci/pcireg.h>
53 #include <dev/pci/pcib_private.h>
54 
55 #include <machine/cpu.h>
56 #include <machine/bus.h>
57 #include <machine/intr.h>
58 #include <vm/vm_page.h>
59 
60 #include "pcib_if.h"
61 
62 /* Assembling ECAM Configuration Address */
63 #define	PCIE_BUS_SHIFT		20
64 #define	PCIE_SLOT_SHIFT		15
65 #define	PCIE_FUNC_SHIFT		12
66 #define	PCIE_BUS_MASK		0xFF
67 #define	PCIE_SLOT_MASK		0x1F
68 #define	PCIE_FUNC_MASK		0x07
69 #define	PCIE_REG_MASK		0xFFF
70 
71 #define	PCIE_ADDR_OFFSET(bus, slot, func, reg)			\
72 	((((bus) & PCIE_BUS_MASK) << PCIE_BUS_SHIFT)	|	\
73 	(((slot) & PCIE_SLOT_MASK) << PCIE_SLOT_SHIFT)	|	\
74 	(((func) & PCIE_FUNC_MASK) << PCIE_FUNC_SHIFT)	|	\
75 	((reg) & PCIE_REG_MASK))
76 
77 #define	MAX_RANGES_TUPLES	5
78 #define	MIN_RANGES_TUPLES	2
79 
80 #define	PCI_IO_WINDOW_OFFSET	0x1000
81 
82 #define	SPACE_CODE_SHIFT	24
83 #define	SPACE_CODE_MASK		0x3
84 #define	SPACE_CODE_IO_SPACE	0x1
85 #define	PROPS_CELL_SIZE		1
86 #define	PCI_ADDR_CELL_SIZE	2
87 
88 struct pcie_range {
89 	uint64_t	pci_base;
90 	uint64_t	phys_base;
91 	uint64_t	size;
92 	uint64_t	flags;
93 #define	FLAG_IO		(1 << 0)
94 #define	FLAG_MEM	(1 << 1)
95 };
96 
97 struct generic_pcie_softc {
98 	struct pcie_range	ranges[MAX_RANGES_TUPLES];
99 	int			nranges;
100 	struct rman		mem_rman;
101 	struct rman		io_rman;
102 	struct resource		*res;
103 	struct resource		*res1;
104 	int			ecam;
105 	bus_space_tag_t		bst;
106 	bus_space_handle_t	bsh;
107 	device_t		dev;
108 	bus_space_handle_t	ioh;
109 	struct ofw_bus_iinfo    pci_iinfo;
110 };
111 
112 /* Forward prototypes */
113 
114 static int generic_pcie_probe(device_t dev);
115 static int generic_pcie_attach(device_t dev);
116 static int parse_pci_mem_ranges(struct generic_pcie_softc *sc);
117 static uint32_t generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
118     u_int func, u_int reg, int bytes);
119 static void generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
120     u_int func, u_int reg, uint32_t val, int bytes);
121 static int generic_pcie_maxslots(device_t dev);
122 static int generic_pcie_read_ivar(device_t dev, device_t child, int index,
123     uintptr_t *result);
124 static int generic_pcie_write_ivar(device_t dev, device_t child, int index,
125     uintptr_t value);
126 static struct resource *generic_pcie_alloc_resource(device_t dev,
127     device_t child, int type, int *rid, rman_res_t start, rman_res_t end,
128     rman_res_t count, u_int flags);
129 static int generic_pcie_release_resource(device_t dev, device_t child,
130     int type, int rid, struct resource *res);
131 
132 static int
133 generic_pcie_probe(device_t dev)
134 {
135 
136 	if (!ofw_bus_status_okay(dev))
137 		return (ENXIO);
138 
139 	if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic")) {
140 		device_set_desc(dev, "Generic PCI host controller");
141 		return (BUS_PROBE_DEFAULT);
142 	}
143 
144 	return (ENXIO);
145 }
146 
147 static int
148 generic_pcie_attach(device_t dev)
149 {
150 	struct generic_pcie_softc *sc;
151 	uint64_t phys_base;
152 	uint64_t pci_base;
153 	uint64_t size;
154 	int error;
155 	int tuple;
156 	int rid;
157 
158 	sc = device_get_softc(dev);
159 	sc->dev = dev;
160 
161 	rid = 0;
162 	sc->res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE);
163 	if (sc->res == NULL) {
164 		device_printf(dev, "could not map memory.\n");
165 		return (ENXIO);
166 	}
167 
168 	sc->bst = rman_get_bustag(sc->res);
169 	sc->bsh = rman_get_bushandle(sc->res);
170 
171 	sc->mem_rman.rm_type = RMAN_ARRAY;
172 	sc->mem_rman.rm_descr = "PCIe Memory";
173 	sc->io_rman.rm_type = RMAN_ARRAY;
174 	sc->io_rman.rm_descr = "PCIe IO window";
175 
176 	/* Retrieve 'ranges' property from FDT */
177 	if (bootverbose)
178 		device_printf(dev, "parsing FDT for ECAM%d:\n",
179 		    sc->ecam);
180 	if (parse_pci_mem_ranges(sc))
181 		return (ENXIO);
182 
183 	/* Initialize rman and allocate memory regions */
184 	error = rman_init(&sc->mem_rman);
185 	if (error) {
186 		device_printf(dev, "rman_init() failed. error = %d\n", error);
187 		return (error);
188 	}
189 
190 	error = rman_init(&sc->io_rman);
191 	if (error) {
192 		device_printf(dev, "rman_init() failed. error = %d\n", error);
193 		return (error);
194 	}
195 
196 	for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
197 		phys_base = sc->ranges[tuple].phys_base;
198 		pci_base = sc->ranges[tuple].pci_base;
199 		size = sc->ranges[tuple].size;
200 		if (phys_base == 0 || size == 0)
201 			continue; /* empty range element */
202 		if (sc->ranges[tuple].flags & FLAG_MEM) {
203 			error = rman_manage_region(&sc->mem_rman,
204 						phys_base,
205 						phys_base + size);
206 		} else if (sc->ranges[tuple].flags & FLAG_IO) {
207 			error = rman_manage_region(&sc->io_rman,
208 					pci_base + PCI_IO_WINDOW_OFFSET,
209 					pci_base + PCI_IO_WINDOW_OFFSET + size);
210 		} else
211 			continue;
212 		if (error) {
213 			device_printf(dev, "rman_manage_region() failed."
214 						"error = %d\n", error);
215 			rman_fini(&sc->mem_rman);
216 			return (error);
217 		}
218 	}
219 
220 	ofw_bus_setup_iinfo(ofw_bus_get_node(dev), &sc->pci_iinfo,
221 	    sizeof(cell_t));
222 
223 
224 	device_add_child(dev, "pci", -1);
225 	return (bus_generic_attach(dev));
226 }
227 
228 static int
229 parse_pci_mem_ranges(struct generic_pcie_softc *sc)
230 {
231 	pcell_t pci_addr_cells, parent_addr_cells;
232 	pcell_t attributes, size_cells;
233 	cell_t *base_ranges;
234 	int nbase_ranges;
235 	phandle_t node;
236 	int i, j, k;
237 	int tuple;
238 
239 	node = ofw_bus_get_node(sc->dev);
240 
241 	OF_getencprop(node, "#address-cells", &pci_addr_cells,
242 					sizeof(pci_addr_cells));
243 	OF_getencprop(node, "#size-cells", &size_cells,
244 					sizeof(size_cells));
245 	OF_getencprop(OF_parent(node), "#address-cells", &parent_addr_cells,
246 					sizeof(parent_addr_cells));
247 
248 	if (parent_addr_cells != 2 || pci_addr_cells != 3 || size_cells != 2) {
249 		device_printf(sc->dev,
250 		    "Unexpected number of address or size cells in FDT\n");
251 		return (ENXIO);
252 	}
253 
254 	nbase_ranges = OF_getproplen(node, "ranges");
255 	sc->nranges = nbase_ranges / sizeof(cell_t) /
256 	    (parent_addr_cells + pci_addr_cells + size_cells);
257 	base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
258 	OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
259 
260 	for (i = 0, j = 0; i < sc->nranges; i++) {
261 		attributes = (base_ranges[j++] >> SPACE_CODE_SHIFT) & \
262 							SPACE_CODE_MASK;
263 		if (attributes == SPACE_CODE_IO_SPACE) {
264 			sc->ranges[i].flags |= FLAG_IO;
265 		} else {
266 			sc->ranges[i].flags |= FLAG_MEM;
267 		}
268 
269 		sc->ranges[i].pci_base = 0;
270 		for (k = 0; k < (pci_addr_cells - 1); k++) {
271 			sc->ranges[i].pci_base <<= 32;
272 			sc->ranges[i].pci_base |= base_ranges[j++];
273 		}
274 		sc->ranges[i].phys_base = 0;
275 		for (k = 0; k < parent_addr_cells; k++) {
276 			sc->ranges[i].phys_base <<= 32;
277 			sc->ranges[i].phys_base |= base_ranges[j++];
278 		}
279 		sc->ranges[i].size = 0;
280 		for (k = 0; k < size_cells; k++) {
281 			sc->ranges[i].size <<= 32;
282 			sc->ranges[i].size |= base_ranges[j++];
283 		}
284 	}
285 
286 	for (; i < MAX_RANGES_TUPLES; i++) {
287 		/* zero-fill remaining tuples to mark empty elements in array */
288 		sc->ranges[i].pci_base = 0;
289 		sc->ranges[i].phys_base = 0;
290 		sc->ranges[i].size = 0;
291 	}
292 
293 	if (bootverbose) {
294 		for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
295 			device_printf(sc->dev,
296 			    "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
297 			    sc->ranges[tuple].pci_base,
298 			    sc->ranges[tuple].phys_base,
299 			    sc->ranges[tuple].size);
300 		}
301 	}
302 
303 	free(base_ranges, M_DEVBUF);
304 	return (0);
305 }
306 
307 static uint32_t
308 generic_pcie_read_config(device_t dev, u_int bus, u_int slot,
309     u_int func, u_int reg, int bytes)
310 {
311 	struct generic_pcie_softc *sc;
312 	bus_space_handle_t h;
313 	bus_space_tag_t	t;
314 	uint64_t offset;
315 	uint32_t data;
316 
317 	if (bus > 255 || slot > 31 || func > 7 || reg > 4095)
318 		return (~0U);
319 
320 	sc = device_get_softc(dev);
321 
322 	offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
323 	t = sc->bst;
324 	h = sc->bsh;
325 
326 	switch (bytes) {
327 	case 1:
328 		data = bus_space_read_1(t, h, offset);
329 		break;
330 	case 2:
331 		data = le16toh(bus_space_read_2(t, h, offset));
332 		break;
333 	case 4:
334 		data = le32toh(bus_space_read_4(t, h, offset));
335 		break;
336 	default:
337 		return (~0U);
338 	}
339 
340 	return (data);
341 }
342 
343 static void
344 generic_pcie_write_config(device_t dev, u_int bus, u_int slot,
345     u_int func, u_int reg, uint32_t val, int bytes)
346 {
347 	struct generic_pcie_softc *sc;
348 	bus_space_handle_t h;
349 	bus_space_tag_t t;
350 	uint64_t offset;
351 
352 	if (bus > 255 || slot > 31 || func > 7 || reg > 4095)
353 		return;
354 
355 	sc = device_get_softc(dev);
356 
357 	offset = PCIE_ADDR_OFFSET(bus, slot, func, reg);
358 
359 	t = sc->bst;
360 	h = sc->bsh;
361 
362 	switch (bytes) {
363 	case 1:
364 		bus_space_write_1(t, h, offset, val);
365 		break;
366 	case 2:
367 		bus_space_write_2(t, h, offset, htole16(val));
368 		break;
369 	case 4:
370 		bus_space_write_4(t, h, offset, htole32(val));
371 		break;
372 	default:
373 		return;
374 	}
375 }
376 
377 static int
378 generic_pcie_maxslots(device_t dev)
379 {
380 
381 	return (31); /* max slots per bus acc. to standard */
382 }
383 
384 static int
385 generic_pcie_route_interrupt(device_t bus, device_t dev, int pin)
386 {
387 	struct generic_pcie_softc *sc;
388 	struct ofw_pci_register reg;
389 	uint32_t pintr, mintr[2];
390 	phandle_t iparent;
391 	int intrcells;
392 
393 	sc = device_get_softc(bus);
394 	pintr = pin;
395 
396 	bzero(&reg, sizeof(reg));
397 	reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
398 	    (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
399 	    (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
400 
401 	intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
402 	    &sc->pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
403 	    mintr, sizeof(mintr), &iparent);
404 	if (intrcells) {
405 		pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
406 		return (pintr);
407 	}
408 
409 	device_printf(bus, "could not route pin %d for device %d.%d\n",
410 	    pin, pci_get_slot(dev), pci_get_function(dev));
411 	return (PCI_INVALID_IRQ);
412 }
413 
414 
415 static int
416 generic_pcie_read_ivar(device_t dev, device_t child, int index,
417     uintptr_t *result)
418 {
419 	struct generic_pcie_softc *sc;
420 	int secondary_bus;
421 
422 	sc = device_get_softc(dev);
423 
424 	if (index == PCIB_IVAR_BUS) {
425 		/* this pcib adds only pci bus 0 as child */
426 		secondary_bus = 0;
427 		*result = secondary_bus;
428 		return (0);
429 
430 	}
431 
432 	if (index == PCIB_IVAR_DOMAIN) {
433 		*result = sc->ecam;
434 		return (0);
435 	}
436 
437 	device_printf(dev, "ERROR: Unknown index.\n");
438 	return (ENOENT);
439 }
440 
441 static int
442 generic_pcie_write_ivar(device_t dev, device_t child, int index,
443     uintptr_t value)
444 {
445 
446 	return (ENOENT);
447 }
448 
449 static struct rman *
450 generic_pcie_rman(struct generic_pcie_softc *sc, int type)
451 {
452 
453 	switch (type) {
454 	case SYS_RES_IOPORT:
455 		return (&sc->io_rman);
456 	case SYS_RES_MEMORY:
457 		return (&sc->mem_rman);
458 	default:
459 		break;
460 	}
461 
462 	return (NULL);
463 }
464 
465 static int
466 generic_pcie_release_resource(device_t dev, device_t child, int type,
467     int rid, struct resource *res)
468 {
469 	struct generic_pcie_softc *sc;
470 	struct rman *rm;
471 
472 	sc = device_get_softc(dev);
473 
474 	rm = generic_pcie_rman(sc, type);
475 	if (rm != NULL) {
476 		KASSERT(rman_is_region_manager(res, rm), ("rman mismatch"));
477 		rman_release_resource(res);
478 	}
479 
480 	return (bus_generic_release_resource(dev, child, type, rid, res));
481 }
482 
483 static struct resource *
484 generic_pcie_alloc_resource(device_t dev, device_t child, int type, int *rid,
485     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
486 {
487 	struct generic_pcie_softc *sc;
488 	struct resource *res;
489 	struct rman *rm;
490 
491 	sc = device_get_softc(dev);
492 
493 	rm = generic_pcie_rman(sc, type);
494 	if (rm == NULL)
495 		return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
496 		    type, rid, start, end, count, flags));
497 
498 	if (bootverbose) {
499 		device_printf(dev,
500 		    "rman_reserve_resource: start=%#lx, end=%#lx, count=%#lx\n",
501 		    start, end, count);
502 	}
503 
504 	res = rman_reserve_resource(rm, start, end, count, flags, child);
505 	if (res == NULL)
506 		goto fail;
507 
508 	rman_set_rid(res, *rid);
509 
510 	if (flags & RF_ACTIVE)
511 		if (bus_activate_resource(child, type, *rid, res)) {
512 			rman_release_resource(res);
513 			goto fail;
514 		}
515 
516 	return (res);
517 
518 fail:
519 	if (bootverbose) {
520 		device_printf(dev, "%s FAIL: type=%d, rid=%d, "
521 		    "start=%016lx, end=%016lx, count=%016lx, flags=%x\n",
522 		    __func__, type, *rid, start, end, count, flags);
523 	}
524 
525 	return (NULL);
526 }
527 
528 static int
529 generic_pcie_adjust_resource(device_t dev, device_t child, int type,
530     struct resource *res, rman_res_t start, rman_res_t end)
531 {
532 	struct generic_pcie_softc *sc;
533 	struct rman *rm;
534 
535 	sc = device_get_softc(dev);
536 
537 	rm = generic_pcie_rman(sc, type);
538 	if (rm != NULL)
539 		return (rman_adjust_resource(res, start, end));
540 	return (bus_generic_adjust_resource(dev, child, type, res, start, end));
541 }
542 
543 static int
544 generic_pcie_activate_resource(device_t dev, device_t child, int type, int rid,
545     struct resource *r)
546 {
547 	struct generic_pcie_softc *sc;
548 	uint64_t phys_base;
549 	uint64_t pci_base;
550 	uint64_t size;
551 	int found;
552 	int res;
553 	int i;
554 
555 	sc = device_get_softc(dev);
556 
557 	if ((res = rman_activate_resource(r)) != 0)
558 		return (res);
559 
560 	switch(type) {
561 	case SYS_RES_IOPORT:
562 		found = 0;
563 		for (i = 0; i < MAX_RANGES_TUPLES; i++) {
564 			pci_base = sc->ranges[i].pci_base;
565 			phys_base = sc->ranges[i].phys_base;
566 			size = sc->ranges[i].size;
567 
568 			if ((rid > pci_base) && (rid < (pci_base + size))) {
569 				found = 1;
570 				break;
571 			}
572 		}
573 		if (found) {
574 			rman_set_start(r, rman_get_start(r) + phys_base);
575 			BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child,
576 						type, rid, r);
577 		} else {
578 			device_printf(dev, "Failed to activate IOPORT resource\n");
579 			res = 0;
580 		}
581 		break;
582 	case SYS_RES_MEMORY:
583 		BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child, type, rid, r);
584 		break;
585 	default:
586 		break;
587 	}
588 
589 	return (res);
590 }
591 
592 static int
593 generic_pcie_deactivate_resource(device_t dev, device_t child, int type, int rid,
594     struct resource *r)
595 {
596 	struct generic_pcie_softc *sc;
597 	vm_offset_t vaddr;
598 	int res;
599 
600 	sc = device_get_softc(dev);
601 
602 	if ((res = rman_deactivate_resource(r)) != 0)
603 		return (res);
604 
605 	switch(type) {
606 	case SYS_RES_IOPORT:
607 	case SYS_RES_MEMORY:
608 		vaddr = (vm_offset_t)rman_get_virtual(r);
609 		pmap_unmapdev(vaddr, rman_get_size(r));
610 		break;
611 	default:
612 		break;
613 	}
614 
615 	return (res);
616 }
617 
618 static device_method_t generic_pcie_methods[] = {
619 	DEVMETHOD(device_probe,			generic_pcie_probe),
620 	DEVMETHOD(device_attach,		generic_pcie_attach),
621 	DEVMETHOD(bus_read_ivar,		generic_pcie_read_ivar),
622 	DEVMETHOD(bus_write_ivar,		generic_pcie_write_ivar),
623 	DEVMETHOD(bus_alloc_resource,		generic_pcie_alloc_resource),
624 	DEVMETHOD(bus_adjust_resource,		generic_pcie_adjust_resource),
625 	DEVMETHOD(bus_release_resource,		generic_pcie_release_resource),
626 	DEVMETHOD(bus_activate_resource,	generic_pcie_activate_resource),
627 	DEVMETHOD(bus_deactivate_resource,	generic_pcie_deactivate_resource),
628 	DEVMETHOD(bus_setup_intr,		bus_generic_setup_intr),
629 	DEVMETHOD(bus_teardown_intr,		bus_generic_teardown_intr),
630 
631 	/* pcib interface */
632 	DEVMETHOD(pcib_maxslots,		generic_pcie_maxslots),
633 	DEVMETHOD(pcib_route_interrupt,		generic_pcie_route_interrupt),
634 	DEVMETHOD(pcib_read_config,		generic_pcie_read_config),
635 	DEVMETHOD(pcib_write_config,		generic_pcie_write_config),
636 #if defined(__aarch64__)
637 	DEVMETHOD(pcib_alloc_msi,		arm_alloc_msi),
638 	DEVMETHOD(pcib_release_msi,		arm_release_msi),
639 	DEVMETHOD(pcib_alloc_msix,		arm_alloc_msix),
640 	DEVMETHOD(pcib_release_msix,		arm_release_msix),
641 	DEVMETHOD(pcib_map_msi,			arm_map_msi),
642 #endif
643 
644 	DEVMETHOD_END
645 };
646 
647 static driver_t generic_pcie_driver = {
648 	"pcib",
649 	generic_pcie_methods,
650 	sizeof(struct generic_pcie_softc),
651 };
652 
653 static devclass_t generic_pcie_devclass;
654 
655 DRIVER_MODULE(pcib, simplebus, generic_pcie_driver,
656 generic_pcie_devclass, 0, 0);
657 DRIVER_MODULE(pcib, ofwbus, generic_pcie_driver,
658 generic_pcie_devclass, 0, 0);
659