xref: /freebsd/sys/dev/bhnd/bhndb/bhndb_pci.c (revision 8ef24a0d4b28fe230e20637f56869cc4148cd2ca)
1 /*-
2  * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer,
10  *    without modification.
11  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13  *    redistribution must be conditioned upon including a substantially
14  *    similar Disclaimer requirement for further binary redistribution.
15  *
16  * NO WARRANTY
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27  * THE POSSIBILITY OF SUCH DAMAGES.
28  */
29 
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32 
33 /*
34  * PCI-specific implementation for the BHNDB bridge driver.
35  *
36  * Provides support for bridging from a PCI parent bus to a BHND-compatible
37  * bus (e.g. bcma or siba) via a Broadcom PCI core configured in end-point
38  * mode.
39  *
40  * This driver handles all initial generic host-level PCI interactions with a
41  * PCI/PCIe bridge core operating in endpoint mode. Once the bridged bhnd(4)
42  * bus has been enumerated, this driver works in tandem with a core-specific
43  * bhnd_pci_hostb driver to manage the PCI core.
44  */
45 
46 #include <sys/param.h>
47 #include <sys/kernel.h>
48 #include <sys/bus.h>
49 #include <sys/limits.h>
50 #include <sys/malloc.h>
51 #include <sys/module.h>
52 #include <sys/systm.h>
53 
54 #include <dev/pci/pcireg.h>
55 #include <dev/pci/pcivar.h>
56 
57 #include <dev/bhnd/bhnd.h>
58 
59 #include <dev/bhnd/cores/pci/bhnd_pcireg.h>
60 
61 #include "bhndb_pcireg.h"
62 #include "bhndb_pcivar.h"
63 #include "bhndb_private.h"
64 
65 static int		bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc);
66 static int		bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc);
67 
68 static int		bhndb_pci_compat_setregwin(struct bhndb_pci_softc *,
69 			    const struct bhndb_regwin *, bhnd_addr_t);
70 static int		bhndb_pci_fast_setregwin(struct bhndb_pci_softc *,
71 			    const struct bhndb_regwin *, bhnd_addr_t);
72 
73 static void		bhndb_init_sromless_pci_config(
74 			    struct bhndb_pci_softc *sc);
75 
76 static bus_addr_t	bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc);
77 static bus_size_t	bhndb_pci_sprom_size(struct bhndb_pci_softc *sc);
78 
79 /**
80  * Default bhndb_pci implementation of device_probe().
81  *
82  * Verifies that the parent is a PCI/PCIe device.
83  */
84 static int
85 bhndb_pci_probe(device_t dev)
86 {
87 	device_t	parent;
88 	devclass_t	parent_bus;
89 	devclass_t	pci;
90 
91 	/* Our parent must be a PCI/PCIe device. */
92 	pci = devclass_find("pci");
93 	parent = device_get_parent(dev);
94 	parent_bus = device_get_devclass(device_get_parent(parent));
95 
96 	if (parent_bus != pci)
97 		return (ENXIO);
98 
99 	device_set_desc(dev, "PCI-BHND bridge");
100 
101 	return (BUS_PROBE_DEFAULT);
102 }
103 
104 static int
105 bhndb_pci_attach(device_t dev)
106 {
107 	struct bhndb_pci_softc	*sc;
108 	int			 error, reg;
109 
110 	sc = device_get_softc(dev);
111 	sc->dev = dev;
112 	sc->parent = device_get_parent(dev);
113 
114 	/* Enable PCI bus mastering */
115 	pci_enable_busmaster(sc->parent);
116 
117 	/* Determine our bridge device class */
118 	sc->pci_devclass = BHND_DEVCLASS_PCI;
119 	if (pci_find_cap(sc->parent, PCIY_EXPRESS, &reg) == 0)
120 		sc->pci_devclass = BHND_DEVCLASS_PCIE;
121 
122 	/* Enable clocks (if supported by this hardware) */
123 	if ((error = bhndb_enable_pci_clocks(sc)))
124 		return (error);
125 
126 	/* Use siba(4)-compatible regwin handling until we know
127 	 * what kind of bus is attached */
128 	sc->set_regwin = bhndb_pci_compat_setregwin;
129 
130 	/* Perform full bridge attach. This should call back into our
131 	 * bhndb_pci_init_full_config() implementation once the bridged
132 	 * bhnd(4) bus has been enumerated, but before any devices have been
133 	 * probed or attached. */
134 	if ((error = bhndb_attach(dev, sc->pci_devclass)))
135 		return (error);
136 
137 	/* If supported, switch to the faster regwin handling */
138 	if (sc->bhndb.chipid.chip_type != BHND_CHIPTYPE_SIBA) {
139 		atomic_store_rel_ptr((volatile void *) &sc->set_regwin,
140 		    (uintptr_t) &bhndb_pci_fast_setregwin);
141 	}
142 
143 	return (0);
144 }
145 
146 static int
147 bhndb_pci_init_full_config(device_t dev, device_t child,
148     const struct bhndb_hw_priority *hw_prio_table)
149 {
150 	struct bhndb_pci_softc	*sc;
151 	device_t		 nv_dev;
152 	bus_size_t		 nv_sz;
153 	int			 error;
154 
155 	sc = device_get_softc(dev);
156 
157 	/* Let our parent perform standard initialization first */
158 	if ((error = bhndb_generic_init_full_config(dev, child, hw_prio_table)))
159 		return (error);
160 
161 	/* Fix-up power on defaults for SROM-less devices. */
162 	bhndb_init_sromless_pci_config(sc);
163 
164 	/* If SPROM is mapped directly into BAR0, add NVRAM device. */
165 	nv_sz = bhndb_pci_sprom_size(sc);
166 	if (nv_sz > 0) {
167 		struct bhndb_devinfo	*dinfo;
168 		const char		*dname;
169 
170 		if (bootverbose) {
171 			device_printf(dev, "found SPROM (%u bytes)\n",
172 			    (unsigned int) nv_sz);
173 		}
174 
175 		/* Add sprom device */
176 		dname = "bhnd_nvram";
177 		if ((nv_dev = BUS_ADD_CHILD(dev, 0, dname, -1)) == NULL) {
178 			device_printf(dev, "failed to add sprom device\n");
179 			return (ENXIO);
180 		}
181 
182 		/* Initialize device address space and resource covering the
183 		 * BAR0 SPROM shadow. */
184 		dinfo = device_get_ivars(nv_dev);
185 		dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
186 		error = bus_set_resource(nv_dev, SYS_RES_MEMORY, 0,
187 		    bhndb_pci_sprom_addr(sc), nv_sz);
188 
189 		if (error) {
190 			device_printf(dev,
191 			    "failed to register sprom resources\n");
192 			return (error);
193 		}
194 
195 		/* Attach the device */
196 		if ((error = device_probe_and_attach(nv_dev))) {
197 			device_printf(dev, "sprom attach failed\n");
198 			return (error);
199 		}
200 	}
201 
202 	return (0);
203 }
204 
205 static const struct bhndb_regwin *
206 bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc)
207 {
208 	struct bhndb_resources		*bres;
209 	const struct bhndb_hwcfg	*cfg;
210 	const struct bhndb_regwin	*sprom_win;
211 
212 	bres = sc->bhndb.bus_res;
213 	cfg = bres->cfg;
214 
215 	sprom_win = bhndb_regwin_find_type(cfg->register_windows,
216 	    BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE);
217 
218 	return (sprom_win);
219 }
220 
221 static bus_addr_t
222 bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc)
223 {
224 	const struct bhndb_regwin	*sprom_win;
225 	struct resource			*r;
226 
227 	/* Fetch the SPROM register window */
228 	sprom_win = bhndb_pci_sprom_regwin(sc);
229 	KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+"));
230 
231 	/* Fetch the associated resource */
232 	r = bhndb_find_regwin_resource(sc->bhndb.bus_res, sprom_win);
233 	KASSERT(r != NULL, ("missing resource for sprom window\n"));
234 
235 	return (rman_get_start(r) + sprom_win->win_offset);
236 }
237 
238 static bus_size_t
239 bhndb_pci_sprom_size(struct bhndb_pci_softc *sc)
240 {
241 	const struct bhndb_regwin	*sprom_win;
242 	uint32_t			 sctl;
243 	bus_size_t			 sprom_sz;
244 
245 	sprom_win = bhndb_pci_sprom_regwin(sc);
246 
247 	/* PCI_V2 and later devices map SPROM/OTP via ChipCommon */
248 	if (sprom_win == NULL)
249 		return (0);
250 
251 	/* Determine SPROM size */
252 	sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4);
253 	if (sctl & BHNDB_PCI_SPROM_BLANK)
254 		return (0);
255 
256 	switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) {
257 	case BHNDB_PCI_SPROM_SZ_1KB:
258 		sprom_sz = (1 * 1024);
259 		break;
260 
261 	case BHNDB_PCI_SPROM_SZ_4KB:
262 		sprom_sz = (4 * 1024);
263 		break;
264 
265 	case BHNDB_PCI_SPROM_SZ_16KB:
266 		sprom_sz = (16 * 1024);
267 		break;
268 
269 	case BHNDB_PCI_SPROM_SZ_RESERVED:
270 	default:
271 		device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl);
272 		return (0);
273 	}
274 
275 	if (sprom_sz > sprom_win->win_size) {
276 		device_printf(sc->dev,
277 		    "PCI sprom size (0x%x) overruns defined register window\n",
278 		    sctl);
279 		return (0);
280 	}
281 
282 	return (sprom_sz);
283 }
284 
285 /*
286  * On devices without a SROM, the PCI(e) cores will be initialized with
287  * their Power-on-Reset defaults; this can leave two of the BAR0 PCI windows
288  * mapped to the wrong core.
289  *
290  * This function updates the SROM shadow to point the BAR0 windows at the
291  * current PCI core.
292  *
293  * Applies to all PCI/PCIe revisions.
294  */
295 static void
296 bhndb_init_sromless_pci_config(struct bhndb_pci_softc *sc)
297 {
298 	struct bhndb_resources		*bres;
299 	const struct bhndb_hwcfg	*cfg;
300 	const struct bhndb_regwin	*win;
301 	struct resource			*core_regs;
302 	bus_size_t			 srom_offset;
303 	u_int				 pci_cidx, sprom_cidx;
304 	uint16_t			 val;
305 
306 	bres = sc->bhndb.bus_res;
307 	cfg = bres->cfg;
308 
309 	if (bhnd_get_vendor(sc->bhndb.hostb_dev) != BHND_MFGID_BCM)
310 		return;
311 
312 	switch (bhnd_get_device(sc->bhndb.hostb_dev)) {
313 	case BHND_COREID_PCI:
314 		srom_offset = BHND_PCI_SRSH_PI_OFFSET;
315 		break;
316 	case BHND_COREID_PCIE:
317 		srom_offset = BHND_PCIE_SRSH_PI_OFFSET;
318 		break;
319 	default:
320 		device_printf(sc->dev, "unsupported PCI host bridge device\n");
321 		return;
322 	}
323 
324 	/* Locate the static register window mapping the PCI core */
325 	win = bhndb_regwin_find_core(cfg->register_windows, sc->pci_devclass,
326 	    0, BHND_PORT_DEVICE, 0, 0);
327 	if (win == NULL) {
328 		device_printf(sc->dev, "missing PCI core register window\n");
329 		return;
330 	}
331 
332 	/* Fetch the resource containing the register window */
333 	core_regs = bhndb_find_regwin_resource(bres, win);
334 	if (core_regs == NULL) {
335 		device_printf(sc->dev, "missing PCI core register resource\n");
336 		return;
337 	}
338 
339 	/* Fetch the SPROM's configured core index */
340 	val = bus_read_2(core_regs, win->win_offset + srom_offset);
341 	sprom_cidx = (val & BHND_PCI_SRSH_PI_MASK) >> BHND_PCI_SRSH_PI_SHIFT;
342 
343 	/* If it doesn't match host bridge's core index, update the index
344 	 * value */
345 	pci_cidx = bhnd_get_core_index(sc->bhndb.hostb_dev);
346 	if (sprom_cidx != pci_cidx) {
347 		val &= ~BHND_PCI_SRSH_PI_MASK;
348 		val |= (pci_cidx << BHND_PCI_SRSH_PI_SHIFT);
349 		bus_write_2(core_regs,
350 		    win->win_offset + srom_offset, val);
351 	}
352 }
353 
354 static int
355 bhndb_pci_resume(device_t dev)
356 {
357 	struct bhndb_pci_softc	*sc;
358 	int			 error;
359 
360 	sc = device_get_softc(dev);
361 
362 	/* Enable clocks (if supported by this hardware) */
363 	if ((error = bhndb_enable_pci_clocks(sc)))
364 		return (error);
365 
366 	/* Perform resume */
367 	return (bhndb_generic_resume(dev));
368 }
369 
370 static int
371 bhndb_pci_suspend(device_t dev)
372 {
373 	struct bhndb_pci_softc	*sc;
374 	int			 error;
375 
376 	sc = device_get_softc(dev);
377 
378 	/* Disable clocks (if supported by this hardware) */
379 	if ((error = bhndb_disable_pci_clocks(sc)))
380 		return (error);
381 
382 	/* Perform suspend */
383 	return (bhndb_generic_suspend(dev));
384 }
385 
386 static int
387 bhndb_pci_detach(device_t dev)
388 {
389 	struct bhndb_pci_softc	*sc;
390 	int			 error;
391 
392 	sc = device_get_softc(dev);
393 
394 	/* Disable clocks (if supported by this hardware) */
395 	if ((error = bhndb_disable_pci_clocks(sc)))
396 		return (error);
397 
398 	/* Perform detach */
399 	if ((error = bhndb_generic_detach(dev)))
400 		return (error);
401 
402 	/* Disable PCI bus mastering */
403 	pci_disable_busmaster(sc->parent);
404 
405 	return (0);
406 }
407 
408 static int
409 bhndb_pci_set_window_addr(device_t dev, const struct bhndb_regwin *rw,
410     bhnd_addr_t addr)
411 {
412 	struct bhndb_pci_softc *sc = device_get_softc(dev);
413 	return (sc->set_regwin(sc, rw, addr));
414 }
415 
416 /**
417  * A siba(4) and bcma(4)-compatible bhndb_set_window_addr implementation.
418  *
419  * On siba(4) devices, it's possible that writing a PCI window register may
420  * not succeed; it's necessary to immediately read the configuration register
421  * and retry if not set to the desired value.
422  *
423  * This is not necessary on bcma(4) devices, but other than the overhead of
424  * validating the register, there's no harm in performing the verification.
425  */
426 static int
427 bhndb_pci_compat_setregwin(struct bhndb_pci_softc *sc,
428     const struct bhndb_regwin *rw, bhnd_addr_t addr)
429 {
430 	int		error;
431 	int		reg;
432 
433 	if (rw->win_type != BHNDB_REGWIN_T_DYN)
434 		return (ENODEV);
435 
436 	reg = rw->d.dyn.cfg_offset;
437 	for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) {
438 		if ((error = bhndb_pci_fast_setregwin(sc, rw, addr)))
439 			return (error);
440 
441 		if (pci_read_config(sc->parent, reg, 4) == addr)
442 			return (0);
443 
444 		DELAY(10);
445 	}
446 
447 	/* Unable to set window */
448 	return (ENODEV);
449 }
450 
451 /**
452  * A bcma(4)-only bhndb_set_window_addr implementation.
453  */
454 static int
455 bhndb_pci_fast_setregwin(struct bhndb_pci_softc *sc,
456     const struct bhndb_regwin *rw, bhnd_addr_t addr)
457 {
458 	/* The PCI bridge core only supports 32-bit addressing, regardless
459 	 * of the bus' support for 64-bit addressing */
460 	if (addr > UINT32_MAX)
461 		return (ERANGE);
462 
463 	switch (rw->win_type) {
464 	case BHNDB_REGWIN_T_DYN:
465 		/* Addresses must be page aligned */
466 		if (addr % rw->win_size != 0)
467 			return (EINVAL);
468 
469 		pci_write_config(sc->parent, rw->d.dyn.cfg_offset, addr, 4);
470 		break;
471 	default:
472 		return (ENODEV);
473 	}
474 
475 	return (0);
476 }
477 
478 static int
479 bhndb_pci_populate_board_info(device_t dev, device_t child,
480     struct bhnd_board_info *info)
481 {
482 	struct bhndb_pci_softc	*sc;
483 
484 	sc = device_get_softc(dev);
485 
486 	/*
487 	 * On a subset of Apple BCM4360 modules, always prefer the
488 	 * PCI subdevice to the SPROM-supplied boardtype.
489 	 *
490 	 * TODO:
491 	 *
492 	 * Broadcom's own drivers implement this override, and then later use
493 	 * the remapped BCM4360 board type to determine the required
494 	 * board-specific workarounds.
495 	 *
496 	 * Without access to this hardware, it's unclear why this mapping
497 	 * is done, and we must do the same. If we can survey the hardware
498 	 * in question, it may be possible to replace this behavior with
499 	 * explicit references to the SPROM-supplied boardtype(s) in our
500 	 * quirk definitions.
501 	 */
502 	if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) {
503 		switch (info->board_type) {
504 		case BHND_BOARD_BCM94360X29C:
505 		case BHND_BOARD_BCM94360X29CP2:
506 		case BHND_BOARD_BCM94360X51:
507 		case BHND_BOARD_BCM94360X51P2:
508 			info->board_type = 0;	/* allow override below */
509 			break;
510 		default:
511 			break;
512 		}
513 	}
514 
515 	/* If NVRAM did not supply vendor/type info, provide the PCI
516 	 * subvendor/subdevice values. */
517 	if (info->board_vendor == 0)
518 		info->board_vendor = pci_get_subvendor(sc->parent);
519 
520 	if (info->board_type == 0)
521 		info->board_type = pci_get_subdevice(sc->parent);
522 
523 	return (0);
524 }
525 
526 /**
527  * Enable externally managed clocks, if required.
528  *
529  * Some PCI chipsets (BCM4306, possibly others) chips do not support
530  * the idle low-power clock. Clocking must be bootstrapped at
531  * attach/resume by directly adjusting GPIO registers exposed in the
532  * PCI config space, and correspondingly, explicitly shutdown at
533  * detach/suspend.
534  *
535  * @param sc Bridge driver state.
536  */
537 static int
538 bhndb_enable_pci_clocks(struct bhndb_pci_softc *sc)
539 {
540 	uint32_t		gpio_in, gpio_out, gpio_en;
541 	uint32_t		gpio_flags;
542 	uint16_t		pci_status;
543 
544 	/* Only supported and required on PCI devices */
545 	if (sc->pci_devclass != BHND_DEVCLASS_PCI)
546 		return (0);
547 
548 	/* Read state of XTAL pin */
549 	gpio_in = pci_read_config(sc->parent, BHNDB_PCI_GPIO_IN, 4);
550 	if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON)
551 		return (0); /* already enabled */
552 
553 	/* Fetch current config */
554 	gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
555 	gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
556 
557 	/* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */
558 	gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
559 	gpio_out |= gpio_flags;
560 	gpio_en |= gpio_flags;
561 
562 	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
563 	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
564 	DELAY(1000);
565 
566 	/* Reset PLL_OFF */
567 	gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF;
568 	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
569 	DELAY(5000);
570 
571 	/* Clear any PCI 'sent target-abort' flag. */
572 	pci_status = pci_read_config(sc->parent, PCIR_STATUS, 2);
573 	pci_status &= ~PCIM_STATUS_STABORT;
574 	pci_write_config(sc->parent, PCIR_STATUS, pci_status, 2);
575 
576 	return (0);
577 }
578 
579 /**
580  * Disable externally managed clocks, if required.
581  *
582  * @param sc Bridge driver state.
583  */
584 static int
585 bhndb_disable_pci_clocks(struct bhndb_pci_softc *sc)
586 {
587 	uint32_t	gpio_out, gpio_en;
588 
589 	/* Only supported and required on PCI devices */
590 	if (sc->pci_devclass != BHND_DEVCLASS_PCI)
591 		return (0);
592 
593 	/* Fetch current config */
594 	gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
595 	gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
596 
597 	/* Set PLL_OFF to HIGH, XTAL_ON to LOW. */
598 	gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON;
599 	gpio_out |= BHNDB_PCI_GPIO_PLL_OFF;
600 	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
601 
602 	/* Enable both output pins */
603 	gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
604 	pci_write_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
605 
606 	return (0);
607 }
608 
609 static device_method_t bhndb_pci_methods[] = {
610 	/* Device interface */
611 	DEVMETHOD(device_probe,			bhndb_pci_probe),
612 	DEVMETHOD(device_attach,		bhndb_pci_attach),
613 	DEVMETHOD(device_resume,		bhndb_pci_resume),
614 	DEVMETHOD(device_suspend,		bhndb_pci_suspend),
615 	DEVMETHOD(device_detach,		bhndb_pci_detach),
616 
617 	/* BHNDB interface */
618 	DEVMETHOD(bhndb_init_full_config,	bhndb_pci_init_full_config),
619 	DEVMETHOD(bhndb_set_window_addr,	bhndb_pci_set_window_addr),
620 	DEVMETHOD(bhndb_populate_board_info,	bhndb_pci_populate_board_info),
621 
622 	DEVMETHOD_END
623 };
624 
625 DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods,
626     sizeof(struct bhndb_pci_softc), bhndb_driver);
627 
628 MODULE_VERSION(bhndb_pci, 1);
629 MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1);
630 MODULE_DEPEND(bhndb_pci, bhnd_pcie2_hostb, 1, 1, 1);
631 MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1);
632 MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1);
633 MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1);
634