]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/pci/pci_host_generic_fdt.c
dts: Update our copy to Linux 4.17
[FreeBSD/FreeBSD.git] / sys / dev / pci / pci_host_generic_fdt.c
1 /*-
2  * Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
3  * Copyright (c) 2014,2016 The FreeBSD Foundation
4  * All rights reserved.
5  *
6  * This software was developed by Andrew Turner under
7  * the sponsorship of the FreeBSD Foundation.
8  *
9  * This software was developed by Semihalf under
10  * the sponsorship of the FreeBSD Foundation.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  * notice, this list of conditions and the following disclaimer in the
19  * documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 /* Generic ECAM PCIe driver FDT attachment */
35
36 #include <sys/cdefs.h>
37 __FBSDID("$FreeBSD$");
38
39 #include "opt_platform.h"
40
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/bus.h>
44 #include <sys/kernel.h>
45 #include <sys/malloc.h>
46 #include <sys/module.h>
47 #include <sys/rman.h>
48
49 #if defined(INTRNG)
50 #include <machine/intr.h>
51 #endif
52
53 #include <dev/ofw/openfirm.h>
54 #include <dev/ofw/ofw_bus.h>
55 #include <dev/ofw/ofw_bus_subr.h>
56 #include <dev/ofw/ofw_pci.h>
57
58 #include <dev/pci/pcivar.h>
59 #include <dev/pci/pcireg.h>
60 #include <dev/pci/pcib_private.h>
61 #include <dev/pci/pci_host_generic.h>
62 #include <dev/pci/pci_host_generic_fdt.h>
63
64 #include <machine/intr.h>
65
66 #include "pcib_if.h"
67
68 #define PCI_IO_WINDOW_OFFSET    0x1000
69
70 #define SPACE_CODE_SHIFT        24
71 #define SPACE_CODE_MASK         0x3
72 #define SPACE_CODE_IO_SPACE     0x1
73 #define PROPS_CELL_SIZE         1
74 #define PCI_ADDR_CELL_SIZE      2
75
76 /* OFW bus interface */
77 struct generic_pcie_ofw_devinfo {
78         struct ofw_bus_devinfo  di_dinfo;
79         struct resource_list    di_rl;
80 };
81
82 /* Forward prototypes */
83
84 static int generic_pcie_fdt_probe(device_t dev);
85 static int parse_pci_mem_ranges(device_t, struct generic_pcie_core_softc *);
86 static int generic_pcie_fdt_release_resource(device_t dev, device_t child,
87     int type, int rid, struct resource *res);
88 static int generic_pcie_ofw_bus_attach(device_t);
89 static const struct ofw_bus_devinfo *generic_pcie_ofw_get_devinfo(device_t,
90     device_t);
91
92 static __inline void
93 get_addr_size_cells(phandle_t node, pcell_t *addr_cells, pcell_t *size_cells)
94 {
95
96         *addr_cells = 2;
97         /* Find address cells if present */
98         OF_getencprop(node, "#address-cells", addr_cells, sizeof(*addr_cells));
99
100         *size_cells = 2;
101         /* Find size cells if present */
102         OF_getencprop(node, "#size-cells", size_cells, sizeof(*size_cells));
103 }
104
105 static int
106 generic_pcie_fdt_probe(device_t dev)
107 {
108
109         if (!ofw_bus_status_okay(dev))
110                 return (ENXIO);
111
112         if (ofw_bus_is_compatible(dev, "pci-host-ecam-generic")) {
113                 device_set_desc(dev, "Generic PCI host controller");
114                 return (BUS_PROBE_GENERIC);
115         }
116         if (ofw_bus_is_compatible(dev, "arm,gem5_pcie")) {
117                 device_set_desc(dev, "GEM5 PCIe host controller");
118                 return (BUS_PROBE_DEFAULT);
119         }
120
121         return (ENXIO);
122 }
123
124 int
125 pci_host_generic_attach(device_t dev)
126 {
127         struct generic_pcie_fdt_softc *sc;
128         uint64_t phys_base;
129         uint64_t pci_base;
130         uint64_t size;
131         phandle_t node;
132         int error;
133         int tuple;
134
135         sc = device_get_softc(dev);
136
137         /* Retrieve 'ranges' property from FDT */
138         if (bootverbose)
139                 device_printf(dev, "parsing FDT for ECAM%d:\n", sc->base.ecam);
140         if (parse_pci_mem_ranges(dev, &sc->base))
141                 return (ENXIO);
142
143         /* Attach OFW bus */
144         if (generic_pcie_ofw_bus_attach(dev) != 0)
145                 return (ENXIO);
146
147         node = ofw_bus_get_node(dev);
148         if (sc->base.coherent == 0) {
149                 sc->base.coherent = OF_hasprop(node, "dma-coherent");
150         }
151         if (bootverbose)
152                 device_printf(dev, "Bus is%s cache-coherent\n",
153                     sc->base.coherent ? "" : " not");
154
155         error = pci_host_generic_core_attach(dev);
156         if (error != 0)
157                 return (error);
158
159         for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
160                 phys_base = sc->base.ranges[tuple].phys_base;
161                 pci_base = sc->base.ranges[tuple].pci_base;
162                 size = sc->base.ranges[tuple].size;
163                 if (phys_base == 0 || size == 0)
164                         continue; /* empty range element */
165                 if (sc->base.ranges[tuple].flags & FLAG_MEM) {
166                         error = rman_manage_region(&sc->base.mem_rman,
167                            phys_base, phys_base + size - 1);
168                 } else if (sc->base.ranges[tuple].flags & FLAG_IO) {
169                         error = rman_manage_region(&sc->base.io_rman,
170                            pci_base + PCI_IO_WINDOW_OFFSET,
171                            pci_base + PCI_IO_WINDOW_OFFSET + size - 1);
172                 } else
173                         continue;
174                 if (error) {
175                         device_printf(dev, "rman_manage_region() failed."
176                                                 "error = %d\n", error);
177                         rman_fini(&sc->base.mem_rman);
178                         return (error);
179                 }
180         }
181
182         ofw_bus_setup_iinfo(node, &sc->pci_iinfo, sizeof(cell_t));
183
184         device_add_child(dev, "pci", -1);
185         return (bus_generic_attach(dev));
186 }
187
188 static int
189 parse_pci_mem_ranges(device_t dev, struct generic_pcie_core_softc *sc)
190 {
191         pcell_t pci_addr_cells, parent_addr_cells;
192         pcell_t attributes, size_cells;
193         cell_t *base_ranges;
194         int nbase_ranges;
195         phandle_t node;
196         int i, j, k;
197         int tuple;
198
199         node = ofw_bus_get_node(dev);
200
201         OF_getencprop(node, "#address-cells", &pci_addr_cells,
202                                         sizeof(pci_addr_cells));
203         OF_getencprop(node, "#size-cells", &size_cells,
204                                         sizeof(size_cells));
205         OF_getencprop(OF_parent(node), "#address-cells", &parent_addr_cells,
206                                         sizeof(parent_addr_cells));
207
208         if (parent_addr_cells > 2 || pci_addr_cells != 3 || size_cells > 2) {
209                 device_printf(dev,
210                     "Unexpected number of address or size cells in FDT\n");
211                 return (ENXIO);
212         }
213
214         nbase_ranges = OF_getproplen(node, "ranges");
215         sc->nranges = nbase_ranges / sizeof(cell_t) /
216             (parent_addr_cells + pci_addr_cells + size_cells);
217         base_ranges = malloc(nbase_ranges, M_DEVBUF, M_WAITOK);
218         OF_getencprop(node, "ranges", base_ranges, nbase_ranges);
219
220         for (i = 0, j = 0; i < sc->nranges; i++) {
221                 attributes = (base_ranges[j++] >> SPACE_CODE_SHIFT) & \
222                                                         SPACE_CODE_MASK;
223                 if (attributes == SPACE_CODE_IO_SPACE) {
224                         sc->ranges[i].flags |= FLAG_IO;
225                 } else {
226                         sc->ranges[i].flags |= FLAG_MEM;
227                 }
228
229                 sc->ranges[i].pci_base = 0;
230                 for (k = 0; k < (pci_addr_cells - 1); k++) {
231                         sc->ranges[i].pci_base <<= 32;
232                         sc->ranges[i].pci_base |= base_ranges[j++];
233                 }
234                 sc->ranges[i].phys_base = 0;
235                 for (k = 0; k < parent_addr_cells; k++) {
236                         sc->ranges[i].phys_base <<= 32;
237                         sc->ranges[i].phys_base |= base_ranges[j++];
238                 }
239                 sc->ranges[i].size = 0;
240                 for (k = 0; k < size_cells; k++) {
241                         sc->ranges[i].size <<= 32;
242                         sc->ranges[i].size |= base_ranges[j++];
243                 }
244         }
245
246         for (; i < MAX_RANGES_TUPLES; i++) {
247                 /* zero-fill remaining tuples to mark empty elements in array */
248                 sc->ranges[i].pci_base = 0;
249                 sc->ranges[i].phys_base = 0;
250                 sc->ranges[i].size = 0;
251         }
252
253         if (bootverbose) {
254                 for (tuple = 0; tuple < MAX_RANGES_TUPLES; tuple++) {
255                         device_printf(dev,
256                             "\tPCI addr: 0x%jx, CPU addr: 0x%jx, Size: 0x%jx\n",
257                             sc->ranges[tuple].pci_base,
258                             sc->ranges[tuple].phys_base,
259                             sc->ranges[tuple].size);
260                 }
261         }
262
263         free(base_ranges, M_DEVBUF);
264         return (0);
265 }
266
267 static int
268 generic_pcie_fdt_route_interrupt(device_t bus, device_t dev, int pin)
269 {
270         struct generic_pcie_fdt_softc *sc;
271         struct ofw_pci_register reg;
272         uint32_t pintr, mintr[4];
273         phandle_t iparent;
274         int intrcells;
275
276         sc = device_get_softc(bus);
277         pintr = pin;
278
279         bzero(&reg, sizeof(reg));
280         reg.phys_hi = (pci_get_bus(dev) << OFW_PCI_PHYS_HI_BUSSHIFT) |
281             (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) |
282             (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT);
283
284         intrcells = ofw_bus_lookup_imap(ofw_bus_get_node(dev),
285             &sc->pci_iinfo, &reg, sizeof(reg), &pintr, sizeof(pintr),
286             mintr, sizeof(mintr), &iparent);
287         if (intrcells) {
288                 pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr);
289                 return (pintr);
290         }
291
292         device_printf(bus, "could not route pin %d for device %d.%d\n",
293             pin, pci_get_slot(dev), pci_get_function(dev));
294         return (PCI_INVALID_IRQ);
295 }
296
297 static int
298 generic_pcie_fdt_release_resource(device_t dev, device_t child, int type,
299     int rid, struct resource *res)
300 {
301
302 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
303         if (type == PCI_RES_BUS) {
304                 return (pci_host_generic_core_release_resource(dev, child, type,
305                     rid, res));
306         }
307 #endif
308
309         /* For PCIe devices that do not have FDT nodes, use PCIB method */
310         if ((int)ofw_bus_get_node(child) <= 0) {
311                 return (pci_host_generic_core_release_resource(dev, child, type,
312                     rid, res));
313         }
314
315         /* For other devices use OFW method */
316         return (bus_generic_release_resource(dev, child, type, rid, res));
317 }
318
319 struct resource *
320 pci_host_generic_alloc_resource(device_t dev, device_t child, int type,
321     int *rid, rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
322 {
323         struct generic_pcie_fdt_softc *sc;
324         struct generic_pcie_ofw_devinfo *di;
325         struct resource_list_entry *rle;
326         int i;
327
328 #if defined(NEW_PCIB) && defined(PCI_RES_BUS)
329         if (type == PCI_RES_BUS) {
330                 return (pci_host_generic_core_alloc_resource(dev, child, type, rid,
331                     start, end, count, flags));
332         }
333 #endif
334
335         /* For PCIe devices that do not have FDT nodes, use PCIB method */
336         if ((int)ofw_bus_get_node(child) <= 0)
337                 return (pci_host_generic_core_alloc_resource(dev, child, type,
338                     rid, start, end, count, flags));
339
340         /* For other devices use OFW method */
341         sc = device_get_softc(dev);
342
343         if (RMAN_IS_DEFAULT_RANGE(start, end)) {
344                 if ((di = device_get_ivars(child)) == NULL)
345                         return (NULL);
346                 if (type == SYS_RES_IOPORT)
347                     type = SYS_RES_MEMORY;
348
349                 /* Find defaults for this rid */
350                 rle = resource_list_find(&di->di_rl, type, *rid);
351                 if (rle == NULL)
352                         return (NULL);
353
354                 start = rle->start;
355                 end = rle->end;
356                 count = rle->count;
357         }
358
359         if (type == SYS_RES_MEMORY) {
360                 /* Remap through ranges property */
361                 for (i = 0; i < MAX_RANGES_TUPLES; i++) {
362                         if (start >= sc->base.ranges[i].phys_base &&
363                             end < (sc->base.ranges[i].pci_base +
364                             sc->base.ranges[i].size)) {
365                                 start -= sc->base.ranges[i].phys_base;
366                                 start += sc->base.ranges[i].pci_base;
367                                 end -= sc->base.ranges[i].phys_base;
368                                 end += sc->base.ranges[i].pci_base;
369                                 break;
370                         }
371                 }
372
373                 if (i == MAX_RANGES_TUPLES) {
374                         device_printf(dev, "Could not map resource "
375                             "%#jx-%#jx\n", start, end);
376                         return (NULL);
377                 }
378         }
379
380         return (bus_generic_alloc_resource(dev, child, type, rid, start,
381             end, count, flags));
382 }
383
384 static int
385 generic_pcie_fdt_activate_resource(device_t dev, device_t child, int type,
386     int rid, struct resource *r)
387 {
388         struct generic_pcie_fdt_softc *sc;
389         uint64_t phys_base;
390         uint64_t pci_base;
391         uint64_t size;
392         int found;
393         int res;
394         int i;
395
396         sc = device_get_softc(dev);
397
398         if ((res = rman_activate_resource(r)) != 0)
399                 return (res);
400
401         switch(type) {
402         case SYS_RES_IOPORT:
403                 found = 0;
404                 for (i = 0; i < MAX_RANGES_TUPLES; i++) {
405                         pci_base = sc->base.ranges[i].pci_base;
406                         phys_base = sc->base.ranges[i].phys_base;
407                         size = sc->base.ranges[i].size;
408
409                         if ((rid > pci_base) && (rid < (pci_base + size))) {
410                                 found = 1;
411                                 break;
412                         }
413                 }
414                 if (found) {
415                         rman_set_start(r, rman_get_start(r) + phys_base);
416                         rman_set_end(r, rman_get_end(r) + phys_base);
417                         res = BUS_ACTIVATE_RESOURCE(device_get_parent(dev),
418                             child, type, rid, r);
419                 } else {
420                         device_printf(dev,
421                             "Failed to activate IOPORT resource\n");
422                         res = 0;
423                 }
424                 break;
425         case SYS_RES_MEMORY:
426                 res = BUS_ACTIVATE_RESOURCE(device_get_parent(dev), child,
427                     type, rid, r);
428                 break;
429         default:
430                 break;
431         }
432
433         return (res);
434 }
435
436 static int
437 generic_pcie_fdt_deactivate_resource(device_t dev, device_t child, int type,
438     int rid, struct resource *r)
439 {
440         int res;
441
442         if ((res = rman_deactivate_resource(r)) != 0)
443                 return (res);
444
445         switch(type) {
446         case SYS_RES_IOPORT:
447         case SYS_RES_MEMORY:
448                 res = BUS_DEACTIVATE_RESOURCE(device_get_parent(dev), child,
449                     type, rid, r);
450                 break;
451         default:
452                 break;
453         }
454
455         return (res);
456 }
457
458 static int
459 generic_pcie_fdt_alloc_msi(device_t pci, device_t child, int count,
460     int maxcount, int *irqs)
461 {
462 #if defined(INTRNG)
463         phandle_t msi_parent;
464         int err;
465
466         err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
467             &msi_parent, NULL);
468         if (err != 0)
469                 return (err);
470         return (intr_alloc_msi(pci, child, msi_parent, count, maxcount,
471             irqs));
472 #else
473         return (ENXIO);
474 #endif
475 }
476
477 static int
478 generic_pcie_fdt_release_msi(device_t pci, device_t child, int count, int *irqs)
479 {
480 #if defined(INTRNG)
481         phandle_t msi_parent;
482         int err;
483
484         err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
485             &msi_parent, NULL);
486         if (err != 0)
487                 return (err);
488         return (intr_release_msi(pci, child, msi_parent, count, irqs));
489 #else
490         return (ENXIO);
491 #endif
492 }
493
494 static int
495 generic_pcie_fdt_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
496     uint32_t *data)
497 {
498 #if defined(INTRNG)
499         phandle_t msi_parent;
500         int err;
501
502         err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
503             &msi_parent, NULL);
504         if (err != 0)
505                 return (err);
506         return (intr_map_msi(pci, child, msi_parent, irq, addr, data));
507 #else
508         return (ENXIO);
509 #endif
510 }
511
512 static int
513 generic_pcie_fdt_alloc_msix(device_t pci, device_t child, int *irq)
514 {
515 #if defined(INTRNG)
516         phandle_t msi_parent;
517         int err;
518
519         err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
520             &msi_parent, NULL);
521         if (err != 0)
522                 return (err);
523         return (intr_alloc_msix(pci, child, msi_parent, irq));
524 #else
525         return (ENXIO);
526 #endif
527 }
528
529 static int
530 generic_pcie_fdt_release_msix(device_t pci, device_t child, int irq)
531 {
532 #if defined(INTRNG)
533         phandle_t msi_parent;
534         int err;
535
536         err = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
537             &msi_parent, NULL);
538         if (err != 0)
539                 return (err);
540         return (intr_release_msix(pci, child, msi_parent, irq));
541 #else
542         return (ENXIO);
543 #endif
544 }
545
546 int
547 generic_pcie_get_id(device_t pci, device_t child, enum pci_id_type type,
548     uintptr_t *id)
549 {
550         phandle_t node;
551         int err;
552         uint32_t rid;
553         uint16_t pci_rid;
554
555         if (type != PCI_ID_MSI)
556                 return (pcib_get_id(pci, child, type, id));
557
558         node = ofw_bus_get_node(pci);
559         pci_rid = pci_get_rid(child);
560
561         err = ofw_bus_msimap(node, pci_rid, NULL, &rid);
562         if (err != 0)
563                 return (err);
564         *id = rid;
565
566         return (0);
567 }
568
569 static const struct ofw_bus_devinfo *
570 generic_pcie_ofw_get_devinfo(device_t bus __unused, device_t child)
571 {
572         struct generic_pcie_ofw_devinfo *di;
573
574         di = device_get_ivars(child);
575         return (&di->di_dinfo);
576 }
577
578 /* Helper functions */
579
580 static int
581 generic_pcie_ofw_bus_attach(device_t dev)
582 {
583         struct generic_pcie_ofw_devinfo *di;
584         device_t child;
585         phandle_t parent, node;
586         pcell_t addr_cells, size_cells;
587
588         parent = ofw_bus_get_node(dev);
589         if (parent > 0) {
590                 get_addr_size_cells(parent, &addr_cells, &size_cells);
591                 /* Iterate through all bus subordinates */
592                 for (node = OF_child(parent); node > 0; node = OF_peer(node)) {
593
594                         /* Allocate and populate devinfo. */
595                         di = malloc(sizeof(*di), M_DEVBUF, M_WAITOK | M_ZERO);
596                         if (ofw_bus_gen_setup_devinfo(&di->di_dinfo, node) != 0) {
597                                 free(di, M_DEVBUF);
598                                 continue;
599                         }
600
601                         /* Initialize and populate resource list. */
602                         resource_list_init(&di->di_rl);
603                         ofw_bus_reg_to_rl(dev, node, addr_cells, size_cells,
604                             &di->di_rl);
605                         ofw_bus_intr_to_rl(dev, node, &di->di_rl, NULL);
606
607                         /* Add newbus device for this FDT node */
608                         child = device_add_child(dev, NULL, -1);
609                         if (child == NULL) {
610                                 resource_list_free(&di->di_rl);
611                                 ofw_bus_gen_destroy_devinfo(&di->di_dinfo);
612                                 free(di, M_DEVBUF);
613                                 continue;
614                         }
615
616                         device_set_ivars(child, di);
617                 }
618         }
619
620         return (0);
621 }
622
623 static device_method_t generic_pcie_fdt_methods[] = {
624         DEVMETHOD(device_probe,         generic_pcie_fdt_probe),
625         DEVMETHOD(device_attach,        pci_host_generic_attach),
626         DEVMETHOD(bus_alloc_resource,   pci_host_generic_alloc_resource),
627         DEVMETHOD(bus_release_resource, generic_pcie_fdt_release_resource),
628         DEVMETHOD(bus_activate_resource, generic_pcie_fdt_activate_resource),
629         DEVMETHOD(bus_deactivate_resource,generic_pcie_fdt_deactivate_resource),
630
631         /* pcib interface */
632         DEVMETHOD(pcib_route_interrupt, generic_pcie_fdt_route_interrupt),
633         DEVMETHOD(pcib_alloc_msi,       generic_pcie_fdt_alloc_msi),
634         DEVMETHOD(pcib_release_msi,     generic_pcie_fdt_release_msi),
635         DEVMETHOD(pcib_alloc_msix,      generic_pcie_fdt_alloc_msix),
636         DEVMETHOD(pcib_release_msix,    generic_pcie_fdt_release_msix),
637         DEVMETHOD(pcib_map_msi,         generic_pcie_fdt_map_msi),
638         DEVMETHOD(pcib_get_id,          generic_pcie_get_id),
639         DEVMETHOD(pcib_request_feature, pcib_request_feature_allow),
640
641         /* ofw_bus interface */
642         DEVMETHOD(ofw_bus_get_devinfo,  generic_pcie_ofw_get_devinfo),
643         DEVMETHOD(ofw_bus_get_compat,   ofw_bus_gen_get_compat),
644         DEVMETHOD(ofw_bus_get_model,    ofw_bus_gen_get_model),
645         DEVMETHOD(ofw_bus_get_name,     ofw_bus_gen_get_name),
646         DEVMETHOD(ofw_bus_get_node,     ofw_bus_gen_get_node),
647         DEVMETHOD(ofw_bus_get_type,     ofw_bus_gen_get_type),
648
649         DEVMETHOD_END
650 };
651
652 DEFINE_CLASS_1(pcib, generic_pcie_fdt_driver, generic_pcie_fdt_methods,
653     sizeof(struct generic_pcie_fdt_softc), generic_pcie_core_driver);
654
655 static devclass_t generic_pcie_fdt_devclass;
656
657 DRIVER_MODULE(pcib, simplebus, generic_pcie_fdt_driver,
658     generic_pcie_fdt_devclass, 0, 0);
659 DRIVER_MODULE(pcib, ofwbus, generic_pcie_fdt_driver, generic_pcie_fdt_devclass,
660     0, 0);