xref: /f-stack/freebsd/mips/nlm/xlp_pci.c (revision 22ce4aff)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2003-2012 Broadcom Corporation
5  * All Rights Reserved
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in
15  *    the documentation and/or other materials provided with the
16  *    distribution.
17  *
18  * THIS SOFTWARE IS PROVIDED BY BROADCOM ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL BROADCOM OR CONTRIBUTORS BE LIABLE
22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
26  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
27  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
28  * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/types.h>
37 #include <sys/kernel.h>
38 #include <sys/module.h>
39 #include <sys/malloc.h>
40 #include <sys/bus.h>
41 #include <sys/endian.h>
42 #include <sys/rman.h>
43 #include <sys/pciio.h>
44 
45 #include <machine/bus.h>
46 #include <machine/md_var.h>
47 #include <machine/intr_machdep.h>
48 #include <machine/cpuregs.h>
49 
50 #include <vm/vm.h>
51 #include <vm/vm_param.h>
52 #include <vm/pmap.h>
53 
54 #include <dev/pci/pcivar.h>
55 #include <dev/pci/pcireg.h>
56 #include <dev/pci/pci_private.h>
57 
58 #include <dev/uart/uart.h>
59 #include <dev/uart/uart_bus.h>
60 #include <dev/uart/uart_cpu.h>
61 
62 #include <dev/ofw/openfirm.h>
63 #include <dev/ofw/ofw_bus.h>
64 #include <dev/ofw/ofw_bus_subr.h>
65 
66 #include <mips/nlm/hal/haldefs.h>
67 #include <mips/nlm/interrupt.h>
68 #include <mips/nlm/hal/iomap.h>
69 #include <mips/nlm/hal/mips-extns.h>
70 #include <mips/nlm/hal/pic.h>
71 #include <mips/nlm/hal/bridge.h>
72 #include <mips/nlm/hal/gbu.h>
73 #include <mips/nlm/hal/pcibus.h>
74 #include <mips/nlm/hal/uart.h>
75 #include <mips/nlm/xlp.h>
76 
77 #include "pcib_if.h"
78 #include <dev/pci/pcib_private.h>
79 #include "pci_if.h"
80 
81 static int
xlp_pci_attach(device_t dev)82 xlp_pci_attach(device_t dev)
83 {
84 	struct pci_devinfo *dinfo;
85 	device_t pcib;
86 	int maxslots, s, f, pcifunchigh, irq;
87 	int busno, node, devoffset;
88 	uint16_t devid;
89 	uint8_t hdrtype;
90 
91 	/*
92 	 * The on-chip devices are on a bus that is almost, but not
93 	 * quite, completely like PCI. Add those things by hand.
94 	 */
95 	pcib = device_get_parent(dev);
96 	busno = pcib_get_bus(dev);
97 	maxslots = PCIB_MAXSLOTS(pcib);
98 	for (s = 0; s <= maxslots; s++) {
99 		pcifunchigh = 0;
100 		f = 0;
101 		hdrtype = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_HDRTYPE, 1);
102 		if ((hdrtype & PCIM_HDRTYPE) > PCI_MAXHDRTYPE)
103 			continue;
104 		if (hdrtype & PCIM_MFDEV)
105 			pcifunchigh = PCI_FUNCMAX;
106 		node = s / 8;
107 		for (f = 0; f <= pcifunchigh; f++) {
108 			devoffset = XLP_HDR_OFFSET(node, 0, s % 8, f);
109 			if (!nlm_dev_exists(devoffset))
110 				continue;
111 
112 			/* Find if there is a desc for the SoC device */
113 			devid = PCIB_READ_CONFIG(pcib, busno, s, f, PCIR_DEVICE, 2);
114 
115 			/* Skip devices that don't have a proper PCI header */
116 			switch (devid) {
117 			case PCI_DEVICE_ID_NLM_ICI:
118 			case PCI_DEVICE_ID_NLM_PIC:
119 			case PCI_DEVICE_ID_NLM_FMN:
120 			case PCI_DEVICE_ID_NLM_UART:
121 			case PCI_DEVICE_ID_NLM_I2C:
122 			case PCI_DEVICE_ID_NLM_NOR:
123 			case PCI_DEVICE_ID_NLM_MMC:
124 				continue;
125 			case PCI_DEVICE_ID_NLM_EHCI:
126 				irq = PIC_USB_IRQ(f);
127 				PCIB_WRITE_CONFIG(pcib, busno, s, f,
128 				    XLP_PCI_DEVSCRATCH_REG0 << 2,
129 				    (1 << 8) | irq, 4);
130 			}
131 			dinfo = pci_read_device(pcib, dev, pcib_get_domain(dev),
132 			    busno, s, f);
133 			pci_add_child(dev, dinfo);
134 		}
135 	}
136 	return (bus_generic_attach(dev));
137 }
138 
139 static int
xlp_pci_probe(device_t dev)140 xlp_pci_probe(device_t dev)
141 {
142 	device_t pcib;
143 
144 	pcib = device_get_parent(dev);
145 	/*
146 	 * Only the top level bus has SoC devices, leave the rest to
147 	 * Generic PCI code
148 	 */
149 	if (strcmp(device_get_nameunit(pcib), "pcib0") != 0)
150 		return (ENXIO);
151 	device_set_desc(dev, "XLP SoCbus");
152 	return (BUS_PROBE_DEFAULT);
153 }
154 
155 static devclass_t pci_devclass;
156 static device_method_t xlp_pci_methods[] = {
157 	/* Device interface */
158 	DEVMETHOD(device_probe,		xlp_pci_probe),
159 	DEVMETHOD(device_attach,	xlp_pci_attach),
160 	DEVMETHOD(bus_rescan,		bus_null_rescan),
161 	DEVMETHOD_END
162 };
163 
164 DEFINE_CLASS_1(pci, xlp_pci_driver, xlp_pci_methods, sizeof(struct pci_softc),
165     pci_driver);
166 DRIVER_MODULE(xlp_pci, pcib, xlp_pci_driver, pci_devclass, 0, 0);
167 
168 static int
xlp_pcib_probe(device_t dev)169 xlp_pcib_probe(device_t dev)
170 {
171 
172 	if (ofw_bus_is_compatible(dev, "netlogic,xlp-pci")) {
173 		device_set_desc(dev, "XLP PCI bus");
174 		return (BUS_PROBE_DEFAULT);
175 	}
176 	return (ENXIO);
177 }
178 
179 static int
xlp_pcib_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)180 xlp_pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
181 {
182 
183 	switch (which) {
184 	case PCIB_IVAR_DOMAIN:
185 		*result = 0;
186 		return (0);
187 	case PCIB_IVAR_BUS:
188 		*result = 0;
189 		return (0);
190 	}
191 	return (ENOENT);
192 }
193 
194 static int
xlp_pcib_write_ivar(device_t dev,device_t child,int which,uintptr_t result)195 xlp_pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t result)
196 {
197 	switch (which) {
198 	case PCIB_IVAR_DOMAIN:
199 		return (EINVAL);
200 	case PCIB_IVAR_BUS:
201 		return (EINVAL);
202 	}
203 	return (ENOENT);
204 }
205 
206 static int
xlp_pcib_maxslots(device_t dev)207 xlp_pcib_maxslots(device_t dev)
208 {
209 
210 	return (PCI_SLOTMAX);
211 }
212 
213 static u_int32_t
xlp_pcib_read_config(device_t dev,u_int b,u_int s,u_int f,u_int reg,int width)214 xlp_pcib_read_config(device_t dev, u_int b, u_int s, u_int f,
215     u_int reg, int width)
216 {
217 	uint32_t data = 0;
218 	uint64_t cfgaddr;
219 	int	regindex = reg/sizeof(uint32_t);
220 
221 	cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
222 	if ((width == 2) && (reg & 1))
223 		return 0xFFFFFFFF;
224 	else if ((width == 4) && (reg & 3))
225 		return 0xFFFFFFFF;
226 
227 	/*
228 	 * The intline and int pin of SoC devices are DOA, except
229 	 * for bridges (slot %8 == 1).
230 	 * use the values we stashed in a writable PCI scratch reg.
231 	 */
232 	if (b == 0 && regindex == 0xf && s % 8 > 1)
233 		regindex = XLP_PCI_DEVSCRATCH_REG0;
234 
235 	data = nlm_read_pci_reg(cfgaddr, regindex);
236 	if (width == 1)
237 		return ((data >> ((reg & 3) << 3)) & 0xff);
238 	else if (width == 2)
239 		return ((data >> ((reg & 3) << 3)) & 0xffff);
240 	else
241 		return (data);
242 }
243 
244 static void
xlp_pcib_write_config(device_t dev,u_int b,u_int s,u_int f,u_int reg,u_int32_t val,int width)245 xlp_pcib_write_config(device_t dev, u_int b, u_int s, u_int f,
246     u_int reg, u_int32_t val, int width)
247 {
248 	uint64_t cfgaddr;
249 	uint32_t data = 0;
250 	int	regindex = reg / sizeof(uint32_t);
251 
252 	cfgaddr = nlm_pcicfg_base(XLP_HDR_OFFSET(0, b, s, f));
253 	if ((width == 2) && (reg & 1))
254 		return;
255 	else if ((width == 4) && (reg & 3))
256 		return;
257 
258 	if (width == 1) {
259 		data = nlm_read_pci_reg(cfgaddr, regindex);
260 		data = (data & ~(0xff << ((reg & 3) << 3))) |
261 		    (val << ((reg & 3) << 3));
262 	} else if (width == 2) {
263 		data = nlm_read_pci_reg(cfgaddr, regindex);
264 		data = (data & ~(0xffff << ((reg & 3) << 3))) |
265 		    (val << ((reg & 3) << 3));
266 	} else {
267 		data = val;
268 	}
269 
270 	/*
271 	 * use shadow reg for intpin/intline which are dead
272 	 */
273 	if (b == 0 && regindex == 0xf && s % 8 > 1)
274 		regindex = XLP_PCI_DEVSCRATCH_REG0;
275 	nlm_write_pci_reg(cfgaddr, regindex, data);
276 }
277 
278 /*
279  * Enable byte swap in hardware when compiled big-endian.
280  * Programs a link's PCIe SWAP regions from the link's IO and MEM address
281  * ranges.
282  */
283 static void
xlp_pcib_hardware_swap_enable(int node,int link)284 xlp_pcib_hardware_swap_enable(int node, int link)
285 {
286 #if BYTE_ORDER == BIG_ENDIAN
287 	uint64_t bbase, linkpcibase;
288 	uint32_t bar;
289 	int pcieoffset;
290 
291 	pcieoffset = XLP_IO_PCIE_OFFSET(node, link);
292 	if (!nlm_dev_exists(pcieoffset))
293 		return;
294 
295 	bbase = nlm_get_bridge_regbase(node);
296 	linkpcibase = nlm_pcicfg_base(pcieoffset);
297 	bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_BASE0 + link);
298 	nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_BASE, bar);
299 
300 	bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEMEM_LIMIT0 + link);
301 	nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_MEM_LIM, bar | 0xFFF);
302 
303 	bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_BASE0 + link);
304 	nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_BASE, bar);
305 
306 	bar = nlm_read_bridge_reg(bbase, BRIDGE_PCIEIO_LIMIT0 + link);
307 	nlm_write_pci_reg(linkpcibase, PCIE_BYTE_SWAP_IO_LIM, bar | 0xFFF);
308 #endif
309 }
310 
311 static int
xlp_pcib_attach(device_t dev)312 xlp_pcib_attach(device_t dev)
313 {
314 	int node, link;
315 
316 	/* enable hardware swap on all nodes/links */
317 	for (node = 0; node < XLP_MAX_NODES; node++)
318 		for (link = 0; link < 4; link++)
319 			xlp_pcib_hardware_swap_enable(node, link);
320 
321 	device_add_child(dev, "pci", -1);
322 	bus_generic_attach(dev);
323 	return (0);
324 }
325 
326 /*
327  * XLS PCIe can have upto 4 links, and each link has its on IRQ
328  * Find the link on which the device is on
329  */
330 static int
xlp_pcie_link(device_t pcib,device_t dev)331 xlp_pcie_link(device_t pcib, device_t dev)
332 {
333 	device_t parent, tmp;
334 
335 	/* find the lane on which the slot is connected to */
336 	tmp = dev;
337 	while (1) {
338 		parent = device_get_parent(tmp);
339 		if (parent == NULL || parent == pcib) {
340 			device_printf(dev, "Cannot find parent bus\n");
341 			return (-1);
342 		}
343 		if (strcmp(device_get_nameunit(parent), "pci0") == 0)
344 			break;
345 		tmp = parent;
346 	}
347 	return (pci_get_function(tmp));
348 }
349 
350 static int
xlp_alloc_msi(device_t pcib,device_t dev,int count,int maxcount,int * irqs)351 xlp_alloc_msi(device_t pcib, device_t dev, int count, int maxcount, int *irqs)
352 {
353 	int i, link;
354 
355 	/*
356 	 * Each link has 32 MSIs that can be allocated, but for now
357 	 * we only support one device per link.
358 	 * msi_alloc() equivalent is needed when we start supporting
359 	 * bridges on the PCIe link.
360 	 */
361 	link = xlp_pcie_link(pcib, dev);
362 	if (link == -1)
363 		return (ENXIO);
364 
365 	/*
366 	 * encode the irq so that we know it is a MSI interrupt when we
367 	 * setup interrupts
368 	 */
369 	for (i = 0; i < count; i++)
370 		irqs[i] = 64 + link * 32 + i;
371 
372 	return (0);
373 }
374 
375 static int
xlp_release_msi(device_t pcib,device_t dev,int count,int * irqs)376 xlp_release_msi(device_t pcib, device_t dev, int count, int *irqs)
377 {
378 	return (0);
379 }
380 
381 static int
xlp_map_msi(device_t pcib,device_t dev,int irq,uint64_t * addr,uint32_t * data)382 xlp_map_msi(device_t pcib, device_t dev, int irq, uint64_t *addr,
383     uint32_t *data)
384 {
385 	int link;
386 
387 	if (irq < 64) {
388 		device_printf(dev, "%s: map_msi for irq %d  - ignored",
389 		    device_get_nameunit(pcib), irq);
390 		return (ENXIO);
391 	}
392 	link = (irq - 64) / 32;
393 	*addr = MIPS_MSI_ADDR(0);
394 	*data = MIPS_MSI_DATA(PIC_PCIE_IRQ(link));
395 	return (0);
396 }
397 
398 static void
bridge_pcie_ack(int irq,void * arg)399 bridge_pcie_ack(int irq, void *arg)
400 {
401 	uint32_t node,reg;
402 	uint64_t base;
403 
404 	node = nlm_nodeid();
405 	reg = PCIE_MSI_STATUS;
406 
407 	switch (irq) {
408 		case PIC_PCIE_0_IRQ:
409 			base = nlm_pcicfg_base(XLP_IO_PCIE0_OFFSET(node));
410 			break;
411 		case PIC_PCIE_1_IRQ:
412 			base = nlm_pcicfg_base(XLP_IO_PCIE1_OFFSET(node));
413 			break;
414 		case PIC_PCIE_2_IRQ:
415 			base = nlm_pcicfg_base(XLP_IO_PCIE2_OFFSET(node));
416 			break;
417 		case PIC_PCIE_3_IRQ:
418 			base = nlm_pcicfg_base(XLP_IO_PCIE3_OFFSET(node));
419 			break;
420 		default:
421 			return;
422 	}
423 
424 	nlm_write_pci_reg(base, reg, 0xFFFFFFFF);
425 	return;
426 }
427 
428 static int
mips_platform_pcib_setup_intr(device_t dev,device_t child,struct resource * irq,int flags,driver_filter_t * filt,driver_intr_t * intr,void * arg,void ** cookiep)429 mips_platform_pcib_setup_intr(device_t dev, device_t child,
430     struct resource *irq, int flags, driver_filter_t *filt,
431     driver_intr_t *intr, void *arg, void **cookiep)
432 {
433 	int error = 0;
434 	int xlpirq;
435 
436 	error = rman_activate_resource(irq);
437 	if (error)
438 		return error;
439 	if (rman_get_start(irq) != rman_get_end(irq)) {
440 		device_printf(dev, "Interrupt allocation %ju != %ju\n",
441 		    rman_get_start(irq), rman_get_end(irq));
442 		return (EINVAL);
443 	}
444 	xlpirq = rman_get_start(irq);
445 	if (xlpirq == 0)
446 		return (0);
447 
448 	if (strcmp(device_get_name(dev), "pcib") != 0)
449 		return (0);
450 
451 	/*
452 	 * temporary hack for MSI, we support just one device per
453 	 * link, and assign the link interrupt to the device interrupt
454 	 */
455 	if (xlpirq >= 64) {
456 		int node, val, link;
457 		uint64_t base;
458 
459 		xlpirq -= 64;
460 		if (xlpirq % 32 != 0)
461 			return (0);
462 
463 		node = nlm_nodeid();
464 		link = xlpirq / 32;
465 		base = nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node,link));
466 
467 		/* MSI Interrupt Vector enable at bridge's configuration */
468 		nlm_write_pci_reg(base, PCIE_MSI_EN, PCIE_MSI_VECTOR_INT_EN);
469 
470 		val = nlm_read_pci_reg(base, PCIE_INT_EN0);
471 		/* MSI Interrupt enable at bridge's configuration */
472 		nlm_write_pci_reg(base, PCIE_INT_EN0,
473 		    (val | PCIE_MSI_INT_EN));
474 
475 		/* legacy interrupt disable at bridge */
476 		val = nlm_read_pci_reg(base, PCIE_BRIDGE_CMD);
477 		nlm_write_pci_reg(base, PCIE_BRIDGE_CMD,
478 		    (val | PCIM_CMD_INTxDIS));
479 
480 		/* MSI address update at bridge */
481 		nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRL,
482 		    MSI_MIPS_ADDR_BASE);
483 		nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_ADDRH, 0);
484 
485 		val = nlm_read_pci_reg(base, PCIE_BRIDGE_MSI_CAP);
486 		/* MSI capability enable at bridge */
487 		nlm_write_pci_reg(base, PCIE_BRIDGE_MSI_CAP,
488 		    (val | (PCIM_MSICTRL_MSI_ENABLE << 16) |
489 		        (PCIM_MSICTRL_MMC_32 << 16)));
490 		xlpirq = PIC_PCIE_IRQ(link);
491 	}
492 
493 	/* if it is for real PCIe, we need to ack at bridge too */
494 	if (xlpirq >= PIC_PCIE_IRQ(0) && xlpirq <= PIC_PCIE_IRQ(3))
495 		xlp_set_bus_ack(xlpirq, bridge_pcie_ack, NULL);
496 	cpu_establish_hardintr(device_get_name(child), filt, intr, arg,
497 	    xlpirq, flags, cookiep);
498 
499 	return (0);
500 }
501 
502 static int
mips_platform_pcib_teardown_intr(device_t dev,device_t child,struct resource * irq,void * cookie)503 mips_platform_pcib_teardown_intr(device_t dev, device_t child,
504     struct resource *irq, void *cookie)
505 {
506 	if (strcmp(device_get_name(child), "pci") == 0) {
507 		/* if needed reprogram the pic to clear pcix related entry */
508 		device_printf(dev, "teardown intr\n");
509 	}
510 	return (bus_generic_teardown_intr(dev, child, irq, cookie));
511 }
512 
513 static int
mips_pcib_route_interrupt(device_t bus,device_t dev,int pin)514 mips_pcib_route_interrupt(device_t bus, device_t dev, int pin)
515 {
516 	int f, d;
517 
518 	/*
519 	 * Validate requested pin number.
520 	 */
521 	if ((pin < 1) || (pin > 4))
522 		return (255);
523 
524 	if (pci_get_bus(dev) == 0 &&
525 	    pci_get_vendor(dev) == PCI_VENDOR_NETLOGIC) {
526 		f = pci_get_function(dev);
527 		d = pci_get_slot(dev) % 8;
528 
529 		/*
530 		 * For PCIe links, return link IRT, for other SoC devices
531 		 * get the IRT from its PCIe header
532 		 */
533 		if (d == 1)
534 			return (PIC_PCIE_IRQ(f));
535 		else
536 			return (255);	/* use intline, don't reroute */
537 	} else {
538 		/* Regular PCI devices */
539 		return (PIC_PCIE_IRQ(xlp_pcie_link(bus, dev)));
540 	}
541 }
542 
543 static device_method_t xlp_pcib_methods[] = {
544 	/* Device interface */
545 	DEVMETHOD(device_probe, xlp_pcib_probe),
546 	DEVMETHOD(device_attach, xlp_pcib_attach),
547 
548 	/* Bus interface */
549 	DEVMETHOD(bus_read_ivar, xlp_pcib_read_ivar),
550 	DEVMETHOD(bus_write_ivar, xlp_pcib_write_ivar),
551 	DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
552 	DEVMETHOD(bus_release_resource, bus_generic_release_resource),
553 	DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
554 	DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
555 	DEVMETHOD(bus_setup_intr, mips_platform_pcib_setup_intr),
556 	DEVMETHOD(bus_teardown_intr, mips_platform_pcib_teardown_intr),
557 
558 	/* pcib interface */
559 	DEVMETHOD(pcib_maxslots, xlp_pcib_maxslots),
560 	DEVMETHOD(pcib_read_config, xlp_pcib_read_config),
561 	DEVMETHOD(pcib_write_config, xlp_pcib_write_config),
562 	DEVMETHOD(pcib_route_interrupt, mips_pcib_route_interrupt),
563 	DEVMETHOD(pcib_request_feature,	pcib_request_feature_allow),
564 
565 	DEVMETHOD(pcib_alloc_msi, xlp_alloc_msi),
566 	DEVMETHOD(pcib_release_msi, xlp_release_msi),
567 	DEVMETHOD(pcib_map_msi, xlp_map_msi),
568 
569 	DEVMETHOD_END
570 };
571 
572 static driver_t xlp_pcib_driver = {
573 	"pcib",
574 	xlp_pcib_methods,
575 	1, /* no softc */
576 };
577 
578 static devclass_t pcib_devclass;
579 DRIVER_MODULE(xlp_pcib, simplebus, xlp_pcib_driver, pcib_devclass, 0, 0);
580