]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/xilinx/xlnx_pcib.c
Merge ^/head r357179 through r357269.
[FreeBSD/FreeBSD.git] / sys / dev / xilinx / xlnx_pcib.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2020 Ruslan Bukin <br@bsdpad.com>
5  *
6  * This software was developed by SRI International and the University of
7  * Cambridge Computer Laboratory (Department of Computer Science and
8  * Technology) under DARPA contract HR0011-18-C-0016 ("ECATS"), as part of the
9  * DARPA SSITH research programme.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions and the following disclaimer.
16  * 2. Redistributions in binary form must reproduce the above copyright
17  *    notice, this list of conditions and the following disclaimer in the
18  *    documentation and/or other materials provided with the distribution.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32
33 #include "opt_platform.h"
34
35 #include <sys/cdefs.h>
36 __FBSDID("$FreeBSD$");
37
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/malloc.h>
41 #include <sys/types.h>
42 #include <sys/sysctl.h>
43 #include <sys/kernel.h>
44 #include <sys/rman.h>
45 #include <sys/module.h>
46 #include <sys/bus.h>
47 #include <sys/endian.h>
48 #include <sys/cpuset.h>
49 #include <sys/mutex.h>
50 #include <sys/proc.h>
51
52 #include <machine/intr.h>
53 #include <machine/bus.h>
54
55 #include <vm/vm.h>
56 #include <vm/vm_extern.h>
57 #include <vm/vm_kern.h>
58 #include <vm/pmap.h>
59
60 #include <dev/ofw/openfirm.h>
61 #include <dev/ofw/ofw_bus.h>
62 #include <dev/ofw/ofw_bus_subr.h>
63
64 #include <dev/pci/pcireg.h>
65 #include <dev/pci/pcivar.h>
66 #include <dev/pci/pci_host_generic.h>
67 #include <dev/pci/pci_host_generic_fdt.h>
68 #include <dev/pci/pcib_private.h>
69
70 #include "xlnx_pcib.h"
71
72 #include "ofw_bus_if.h"
73 #include "msi_if.h"
74 #include "pcib_if.h"
75 #include "pic_if.h"
76
77 #define XLNX_PCIB_MAX_MSI       64
78
79 static int xlnx_pcib_fdt_attach(device_t);
80 static int xlnx_pcib_fdt_probe(device_t);
81 static int xlnx_pcib_fdt_get_id(device_t, device_t, enum pci_id_type,
82     uintptr_t *);
83 static void xlnx_pcib_msi_mask(device_t dev, struct intr_irqsrc *isrc,
84     bool mask);
85
86 struct xlnx_pcib_softc {
87         struct generic_pcie_fdt_softc   fdt_sc;
88         struct resource                 *res[4];
89         struct mtx                      mtx;
90         vm_offset_t                     msi_page;
91         struct xlnx_pcib_irqsrc         *isrcs;
92         device_t                        dev;
93         void                            *intr_cookie[3];
94 };
95
96 static struct resource_spec xlnx_pcib_spec[] = {
97         { SYS_RES_MEMORY,       0,      RF_ACTIVE },
98         { SYS_RES_IRQ,          0,      RF_ACTIVE },
99         { SYS_RES_IRQ,          1,      RF_ACTIVE },
100         { SYS_RES_IRQ,          2,      RF_ACTIVE },
101         { -1, 0 }
102 };
103
104 struct xlnx_pcib_irqsrc {
105         struct intr_irqsrc      isrc;
106         u_int                   irq;
107 #define XLNX_IRQ_FLAG_USED      (1 << 0)
108         u_int                   flags;
109 };
110
111 static void
112 xlnx_pcib_clear_err_interrupts(struct generic_pcie_core_softc *sc)
113 {
114         uint32_t reg;
115
116         reg = bus_read_4(sc->res, XLNX_PCIE_RPERRFRR);
117
118         if (reg & RPERRFRR_VALID) {
119                 device_printf(sc->dev, "Requested ID: %x\n",
120                     reg & RPERRFRR_REQ_ID_M);
121                 bus_write_4(sc->res, XLNX_PCIE_RPERRFRR, ~0U);
122         }
123 }
124
125 static int
126 xlnx_pcib_intr(void *arg)
127 {
128         struct generic_pcie_fdt_softc *fdt_sc;
129         struct generic_pcie_core_softc *sc;
130         struct xlnx_pcib_softc *xlnx_sc;
131         uint32_t val, mask, status;
132
133         xlnx_sc = arg;
134         fdt_sc = &xlnx_sc->fdt_sc;
135         sc = &fdt_sc->base;
136
137         val = bus_read_4(sc->res, XLNX_PCIE_IDR);
138         mask = bus_read_4(sc->res, XLNX_PCIE_IMR);
139
140         status = val & mask;
141         if (!status)
142                 return (FILTER_HANDLED);
143
144         if (status & IMR_LINK_DOWN)
145                 device_printf(sc->dev, "Link down");
146
147         if (status & IMR_HOT_RESET)
148                 device_printf(sc->dev, "Hot reset");
149
150         if (status & IMR_CORRECTABLE)
151                 xlnx_pcib_clear_err_interrupts(sc);
152
153         if (status & IMR_FATAL)
154                 xlnx_pcib_clear_err_interrupts(sc);
155
156         if (status & IMR_NON_FATAL)
157                 xlnx_pcib_clear_err_interrupts(sc);
158
159         if (status & IMR_MSI) {
160                 device_printf(sc->dev, "MSI interrupt");
161
162                 /* FIFO mode MSI not implemented. */
163         }
164
165         if (status & IMR_INTX) {
166                 device_printf(sc->dev, "INTx received");
167
168                 /* Not implemented. */
169         }
170
171         if (status & IMR_SLAVE_UNSUPP_REQ)
172                 device_printf(sc->dev, "Slave unsupported request");
173
174         if (status & IMR_SLAVE_UNEXP_COMPL)
175                 device_printf(sc->dev, "Slave unexpected completion");
176
177         if (status & IMR_SLAVE_COMPL_TIMOUT)
178                 device_printf(sc->dev, "Slave completion timeout");
179
180         if (status & IMR_SLAVE_ERROR_POISON)
181                 device_printf(sc->dev, "Slave error poison");
182
183         if (status & IMR_SLAVE_COMPL_ABORT)
184                 device_printf(sc->dev, "Slave completion abort");
185
186         if (status & IMR_SLAVE_ILLEG_BURST)
187                 device_printf(sc->dev, "Slave illegal burst");
188
189         if (status & IMR_MASTER_DECERR)
190                 device_printf(sc->dev, "Master decode error");
191
192         if (status & IMR_MASTER_SLVERR)
193                 device_printf(sc->dev, "Master slave error");
194
195         bus_write_4(sc->res, XLNX_PCIE_IDR, val);
196
197         return (FILTER_HANDLED);
198 }
199
200 static void
201 xlnx_pcib_handle_msi_intr(void *arg, int msireg)
202
203         struct generic_pcie_fdt_softc *fdt_sc;
204         struct generic_pcie_core_softc *sc;
205         struct xlnx_pcib_softc *xlnx_sc;
206         struct xlnx_pcib_irqsrc *xi;
207         struct trapframe *tf;
208         int irq;
209         int reg;
210         int i;
211
212         xlnx_sc = arg;
213         fdt_sc = &xlnx_sc->fdt_sc;
214         sc = &fdt_sc->base;
215         tf = curthread->td_intr_frame;
216
217         do {
218                 reg = bus_read_4(sc->res, msireg);
219
220                 for (i = 0; i < sizeof(uint32_t) * 8; i++) {
221                         if (reg & (1 << i)) {
222                                 bus_write_4(sc->res, msireg, (1 << i));
223
224                                 irq = i;
225                                 if (msireg == XLNX_PCIE_RPMSIID2)
226                                         irq += 32;
227
228                                 xi = &xlnx_sc->isrcs[irq];
229                                 if (intr_isrc_dispatch(&xi->isrc, tf) != 0) {
230                                         /* Disable stray. */
231                                         xlnx_pcib_msi_mask(sc->dev,
232                                             &xi->isrc, 1);
233                                         device_printf(sc->dev,
234                                             "Stray irq %u disabled\n", irq);
235                                 }
236                         }
237                 }
238         } while (reg != 0);
239 }
240
241 static int
242 xlnx_pcib_msi0_intr(void *arg)
243 {
244
245         xlnx_pcib_handle_msi_intr(arg, XLNX_PCIE_RPMSIID1);
246
247         return (FILTER_HANDLED);
248 }
249
250 static int
251 xlnx_pcib_msi1_intr(void *arg)
252 {
253
254         xlnx_pcib_handle_msi_intr(arg, XLNX_PCIE_RPMSIID2);
255
256         return (FILTER_HANDLED);
257 }
258
259 static int
260 xlnx_pcib_register_msi(struct xlnx_pcib_softc *sc)
261 {
262         const char *name;
263         int error;
264         int irq;
265
266         sc->isrcs = malloc(sizeof(*sc->isrcs) * XLNX_PCIB_MAX_MSI, M_DEVBUF,
267             M_WAITOK | M_ZERO);
268
269         name = device_get_nameunit(sc->dev);
270
271         for (irq = 0; irq < XLNX_PCIB_MAX_MSI; irq++) {
272                 sc->isrcs[irq].irq = irq;
273                 error = intr_isrc_register(&sc->isrcs[irq].isrc,
274                     sc->dev, 0, "%s,%u", name, irq);
275                 if (error != 0)
276                         return (error); /* XXX deregister ISRCs */
277         }
278
279         if (intr_msi_register(sc->dev,
280             OF_xref_from_node(ofw_bus_get_node(sc->dev))) != 0)
281                 return (ENXIO);
282
283         return (0);
284 }
285
286 static void
287 xlnx_pcib_init(struct xlnx_pcib_softc *sc)
288 {
289         bus_addr_t addr;
290         int reg;
291
292         /* Disable interrupts. */
293         bus_write_4(sc->res[0], XLNX_PCIE_IMR, 0);
294
295         /* Clear pending interrupts.*/
296         reg = bus_read_4(sc->res[0], XLNX_PCIE_IDR);
297         bus_write_4(sc->res[0], XLNX_PCIE_IDR, reg);
298
299         /* Setup an MSI page. */
300         sc->msi_page = kmem_alloc_contig(PAGE_SIZE, M_WAITOK, 0,
301             BUS_SPACE_MAXADDR, PAGE_SIZE, 0, VM_MEMATTR_DEFAULT);
302         addr = vtophys(sc->msi_page);
303         bus_write_4(sc->res[0], XLNX_PCIE_RPMSIBR1, (addr >> 32));
304         bus_write_4(sc->res[0], XLNX_PCIE_RPMSIBR2, (addr >>  0));
305
306         /* Enable the bridge. */
307         reg = bus_read_4(sc->res[0], XLNX_PCIE_RPSCR);
308         reg |= RPSCR_BE;
309         bus_write_4(sc->res[0], XLNX_PCIE_RPSCR, reg);
310
311         /* Enable interrupts. */
312         reg = IMR_LINK_DOWN
313                 | IMR_HOT_RESET
314                 | IMR_CFG_COMPL_STATUS_M
315                 | IMR_CFG_TIMEOUT
316                 | IMR_CORRECTABLE
317                 | IMR_NON_FATAL
318                 | IMR_FATAL
319                 | IMR_INTX
320                 | IMR_MSI
321                 | IMR_SLAVE_UNSUPP_REQ
322                 | IMR_SLAVE_UNEXP_COMPL
323                 | IMR_SLAVE_COMPL_TIMOUT
324                 | IMR_SLAVE_ERROR_POISON
325                 | IMR_SLAVE_COMPL_ABORT
326                 | IMR_SLAVE_ILLEG_BURST
327                 | IMR_MASTER_DECERR
328                 | IMR_MASTER_SLVERR;
329         bus_write_4(sc->res[0], XLNX_PCIE_IMR, reg);
330 }
331
332 static int
333 xlnx_pcib_fdt_probe(device_t dev)
334 {
335
336         if (!ofw_bus_status_okay(dev))
337                 return (ENXIO);
338
339         if (ofw_bus_is_compatible(dev, "xlnx,xdma-host-3.00")) {
340                 device_set_desc(dev, "Xilinx XDMA PCIe Controller");
341                 return (BUS_PROBE_DEFAULT);
342         }
343
344         return (ENXIO);
345 }
346
347 static int
348 xlnx_pcib_fdt_attach(device_t dev)
349 {
350         struct xlnx_pcib_softc *sc;
351         int error;
352
353         sc = device_get_softc(dev);
354         sc->dev = dev;
355
356         mtx_init(&sc->mtx, "msi_mtx", NULL, MTX_DEF);
357
358         if (bus_alloc_resources(dev, xlnx_pcib_spec, sc->res)) {
359                 device_printf(dev, "could not allocate resources\n");
360                 return (ENXIO);
361         }
362
363         /* Setup MISC interrupt handler. */
364         error = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
365             xlnx_pcib_intr, NULL, sc, &sc->intr_cookie[0]);
366         if (error != 0) {
367                 device_printf(dev, "could not setup interrupt handler.\n");
368                 return (ENXIO);
369         }
370
371         /* Setup MSI0 interrupt handler. */
372         error = bus_setup_intr(dev, sc->res[2], INTR_TYPE_MISC | INTR_MPSAFE,
373             xlnx_pcib_msi0_intr, NULL, sc, &sc->intr_cookie[1]);
374         if (error != 0) {
375                 device_printf(dev, "could not setup interrupt handler.\n");
376                 return (ENXIO);
377         }
378
379         /* Setup MSI1 interrupt handler. */
380         error = bus_setup_intr(dev, sc->res[3], INTR_TYPE_MISC | INTR_MPSAFE,
381             xlnx_pcib_msi1_intr, NULL, sc, &sc->intr_cookie[2]);
382         if (error != 0) {
383                 device_printf(dev, "could not setup interrupt handler.\n");
384                 return (ENXIO);
385         }
386
387         xlnx_pcib_init(sc);
388
389         /*
390          * Allow the core driver to map registers.
391          * We will be accessing the device memory using core_softc.
392          */
393         bus_release_resources(dev, xlnx_pcib_spec, sc->res);
394
395         error = xlnx_pcib_register_msi(sc);
396         if (error)
397                 return (error);
398
399         return (pci_host_generic_attach(dev));
400 }
401
402 static int
403 xlnx_pcib_fdt_get_id(device_t pci, device_t child, enum pci_id_type type,
404     uintptr_t *id)
405 {
406         phandle_t node;
407         int bsf;
408
409         if (type != PCI_ID_MSI)
410                 return (pcib_get_id(pci, child, type, id));
411
412         node = ofw_bus_get_node(pci);
413         if (OF_hasprop(node, "msi-map"))
414                 return (generic_pcie_get_id(pci, child, type, id));
415
416         bsf = pci_get_rid(child);
417         *id = (pci_get_domain(child) << PCI_RID_DOMAIN_SHIFT) | bsf;
418
419         return (0);
420 }
421
422 static int
423 xlnx_pcib_req_valid(struct generic_pcie_core_softc *sc,
424     u_int bus, u_int slot, u_int func, u_int reg)
425 {
426         bus_space_handle_t h;
427         bus_space_tag_t t;
428         uint32_t val;
429
430         t = sc->bst;
431         h = sc->bsh;
432
433         if ((bus < sc->bus_start) || (bus > sc->bus_end))
434                 return (0);
435         if ((slot > PCI_SLOTMAX) || (func > PCI_FUNCMAX) ||
436             (reg > PCIE_REGMAX))
437                 return (0);
438
439         if (bus == 0 && slot > 0)
440                 return (0);
441
442         val = bus_space_read_4(t, h, XLNX_PCIE_PHYSCR);
443         if ((val & PHYSCR_LINK_UP) == 0) {
444                 /* Link is down */
445                 return (0);
446         }
447
448         /* Valid */
449
450         return (1);
451 }
452
453 static uint32_t
454 xlnx_pcib_read_config(device_t dev, u_int bus, u_int slot,
455     u_int func, u_int reg, int bytes)
456 {
457         struct generic_pcie_fdt_softc *fdt_sc;
458         struct xlnx_pcib_softc *xlnx_sc;
459         struct generic_pcie_core_softc *sc;
460         bus_space_handle_t h;
461         bus_space_tag_t t;
462         uint64_t offset;
463         uint32_t data;
464
465         xlnx_sc = device_get_softc(dev);
466         fdt_sc = &xlnx_sc->fdt_sc;
467         sc = &fdt_sc->base;
468
469         if (!xlnx_pcib_req_valid(sc, bus, slot, func, reg))
470                 return (~0U);
471
472         offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg);
473         t = sc->bst;
474         h = sc->bsh;
475
476         data = bus_space_read_4(t, h, offset & ~3);
477
478         switch (bytes) {
479         case 1:
480                 data >>= (offset & 3) * 8;
481                 data &= 0xff;
482                 break;
483         case 2:
484                 data >>= (offset & 3) * 8;
485                 data = le16toh(data);
486                 break;
487         case 4:
488                 data = le32toh(data);
489                 break;
490         default:
491                 return (~0U);
492         }
493
494         return (data);
495 }
496
497 static void
498 xlnx_pcib_write_config(device_t dev, u_int bus, u_int slot,
499     u_int func, u_int reg, uint32_t val, int bytes)
500 {
501         struct generic_pcie_fdt_softc *fdt_sc;
502         struct xlnx_pcib_softc *xlnx_sc;
503         struct generic_pcie_core_softc *sc;
504         bus_space_handle_t h;
505         bus_space_tag_t t;
506         uint64_t offset;
507         uint32_t data;
508
509         xlnx_sc = device_get_softc(dev);
510         fdt_sc = &xlnx_sc->fdt_sc;
511         sc = &fdt_sc->base;
512
513         if (!xlnx_pcib_req_valid(sc, bus, slot, func, reg))
514                 return;
515
516         offset = PCIE_ADDR_OFFSET(bus - sc->bus_start, slot, func, reg);
517
518         t = sc->bst;
519         h = sc->bsh;
520
521         /*
522          * 32-bit access used due to a bug in the Xilinx bridge that
523          * requires to write primary and secondary buses in one blast.
524          *
525          * TODO: This is probably wrong on big-endian.
526          */
527         switch (bytes) {
528         case 1:
529                 data = bus_space_read_4(t, h, offset & ~3);
530                 data &= ~(0xff << ((offset & 3) * 8));
531                 data |= (val & 0xff) << ((offset & 3) * 8);
532                 bus_space_write_4(t, h, offset & ~3, htole32(data));
533                 break;
534         case 2:
535                 data = bus_space_read_4(t, h, offset & ~3);
536                 data &= ~(0xffff << ((offset & 3) * 8));
537                 data |= (val & 0xffff) << ((offset & 3) * 8);
538                 bus_space_write_4(t, h, offset & ~3, htole32(data));
539                 break;
540         case 4:
541                 bus_space_write_4(t, h, offset, htole32(val));
542                 break;
543         default:
544                 return;
545         }
546 }
547
548 static int
549 xlnx_pcib_alloc_msi(device_t pci, device_t child, int count, int maxcount,
550     int *irqs)
551 {
552         phandle_t msi_parent;
553
554         ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
555             NULL);
556         msi_parent = OF_xref_from_node(ofw_bus_get_node(pci));
557         return (intr_alloc_msi(pci, child, msi_parent, count, maxcount,
558             irqs));
559 }
560
561 static int
562 xlnx_pcib_release_msi(device_t pci, device_t child, int count, int *irqs)
563 {
564         phandle_t msi_parent;
565
566         ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
567             NULL);
568         msi_parent = OF_xref_from_node(ofw_bus_get_node(pci));
569         return (intr_release_msi(pci, child, msi_parent, count, irqs));
570 }
571
572 static int
573 xlnx_pcib_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
574     uint32_t *data)
575 {
576         phandle_t msi_parent;
577
578         ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child), &msi_parent,
579             NULL);
580         msi_parent = OF_xref_from_node(ofw_bus_get_node(pci));
581         return (intr_map_msi(pci, child, msi_parent, irq, addr, data));
582 }
583
584 static int
585 xlnx_pcib_msi_alloc_msi(device_t dev, device_t child, int count, int maxcount,
586     device_t *pic, struct intr_irqsrc **srcs)
587 {
588         struct xlnx_pcib_softc *sc;
589         int irq, end_irq, i;
590         bool found;
591
592         sc = device_get_softc(dev);
593
594         mtx_lock(&sc->mtx);
595
596         found = false;
597
598         for (irq = 0; (irq + count - 1) < XLNX_PCIB_MAX_MSI; irq++) {
599
600                 /* Assume the range is valid. */
601                 found = true;
602
603                 /* Check this range is valid. */
604                 for (end_irq = irq; end_irq < irq + count; end_irq++) {
605                         if (sc->isrcs[end_irq].flags & XLNX_IRQ_FLAG_USED) {
606                                 /* This is already used. */
607                                 found = false;
608                                 break;
609                         }
610                 }
611
612                 if (found)
613                         break;
614         }
615
616         if (!found || irq == (XLNX_PCIB_MAX_MSI - 1)) {
617                 /* Not enough interrupts were found. */
618                 mtx_unlock(&sc->mtx);
619                 return (ENXIO);
620         }
621
622         /* Mark the interrupt as used. */
623         for (i = 0; i < count; i++)
624                 sc->isrcs[irq + i].flags |= XLNX_IRQ_FLAG_USED;
625
626         mtx_unlock(&sc->mtx);
627
628         for (i = 0; i < count; i++)
629                 srcs[i] = (struct intr_irqsrc *)&sc->isrcs[irq + i];
630
631         *pic = device_get_parent(dev);
632
633         return (0);
634 }
635
636 static int
637 xlnx_pcib_msi_release_msi(device_t dev, device_t child, int count,
638     struct intr_irqsrc **isrc)
639 {
640         struct xlnx_pcib_softc *sc;
641         struct xlnx_pcib_irqsrc *xi;
642         int i;
643
644         sc = device_get_softc(dev);
645         mtx_lock(&sc->mtx);
646         for (i = 0; i < count; i++) {
647                 xi = (struct xlnx_pcib_irqsrc *)isrc[i];
648
649                 KASSERT(xi->flags & XLNX_IRQ_FLAG_USED,
650                     ("%s: Releasing an unused MSI interrupt", __func__));
651
652                 xi->flags &= ~XLNX_IRQ_FLAG_USED;
653         }
654
655         mtx_unlock(&sc->mtx);
656         return (0);
657 }
658
659 static int
660 xlnx_pcib_msi_map_msi(device_t dev, device_t child, struct intr_irqsrc *isrc,
661     uint64_t *addr, uint32_t *data)
662 {
663         struct xlnx_pcib_softc *sc;
664         struct xlnx_pcib_irqsrc *xi;
665
666         sc = device_get_softc(dev);
667         xi = (struct xlnx_pcib_irqsrc *)isrc;
668
669         *addr = vtophys(sc->msi_page);
670         *data = xi->irq;
671
672         return (0);
673 }
674
675 static void
676 xlnx_pcib_msi_mask(device_t dev, struct intr_irqsrc *isrc, bool mask)
677 {
678         struct generic_pcie_fdt_softc *fdt_sc;
679         struct generic_pcie_core_softc *sc;
680         struct xlnx_pcib_softc *xlnx_sc;
681         struct xlnx_pcib_irqsrc *xi;
682         uint32_t msireg, irq;
683         uint32_t reg;
684
685         xlnx_sc = device_get_softc(dev);
686         fdt_sc = &xlnx_sc->fdt_sc;
687         sc = &fdt_sc->base;
688
689         xi = (struct xlnx_pcib_irqsrc *)isrc;
690
691         irq = xi->irq;
692         if (irq < 32)
693                 msireg = XLNX_PCIE_RPMSIID1_MASK;
694         else
695                 msireg = XLNX_PCIE_RPMSIID2_MASK;
696
697         reg = bus_read_4(sc->res, msireg);
698         if (mask)
699                 reg &= ~(1 << irq);
700         else
701                 reg |= (1 << irq);
702         bus_write_4(sc->res, msireg, reg);
703 }
704
705 static void
706 xlnx_pcib_msi_disable_intr(device_t dev, struct intr_irqsrc *isrc)
707 {
708
709         xlnx_pcib_msi_mask(dev, isrc, true);
710 }
711
712 static void
713 xlnx_pcib_msi_enable_intr(device_t dev, struct intr_irqsrc *isrc)
714 {
715
716         xlnx_pcib_msi_mask(dev, isrc, false);
717 }
718
719 static void
720 xlnx_pcib_msi_post_filter(device_t dev, struct intr_irqsrc *isrc)
721 {
722
723 }
724
725 static void
726 xlnx_pcib_msi_post_ithread(device_t dev, struct intr_irqsrc *isrc)
727 {
728
729         xlnx_pcib_msi_mask(dev, isrc, false);
730 }
731
732 static void
733 xlnx_pcib_msi_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
734 {
735
736         xlnx_pcib_msi_mask(dev, isrc, true);
737 }
738
739 static int
740 xlnx_pcib_msi_setup_intr(device_t dev, struct intr_irqsrc *isrc,
741     struct resource *res, struct intr_map_data *data)
742 {
743
744         return (0);
745 }
746
747 static int
748 xlnx_pcib_msi_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
749     struct resource *res, struct intr_map_data *data)
750 {
751
752         return (0);
753 }
754
755 static device_method_t xlnx_pcib_fdt_methods[] = {
756         /* Device interface */
757         DEVMETHOD(device_probe,         xlnx_pcib_fdt_probe),
758         DEVMETHOD(device_attach,        xlnx_pcib_fdt_attach),
759
760         /* pcib interface */
761         DEVMETHOD(pcib_get_id,          xlnx_pcib_fdt_get_id),
762         DEVMETHOD(pcib_read_config,     xlnx_pcib_read_config),
763         DEVMETHOD(pcib_write_config,    xlnx_pcib_write_config),
764         DEVMETHOD(pcib_alloc_msi,       xlnx_pcib_alloc_msi),
765         DEVMETHOD(pcib_release_msi,     xlnx_pcib_release_msi),
766         DEVMETHOD(pcib_map_msi,         xlnx_pcib_map_msi),
767
768         /* MSI interface */
769         DEVMETHOD(msi_alloc_msi,                xlnx_pcib_msi_alloc_msi),
770         DEVMETHOD(msi_release_msi,              xlnx_pcib_msi_release_msi),
771         DEVMETHOD(msi_map_msi,                  xlnx_pcib_msi_map_msi),
772
773         /* Interrupt controller interface */
774         DEVMETHOD(pic_disable_intr,             xlnx_pcib_msi_disable_intr),
775         DEVMETHOD(pic_enable_intr,              xlnx_pcib_msi_enable_intr),
776         DEVMETHOD(pic_setup_intr,               xlnx_pcib_msi_setup_intr),
777         DEVMETHOD(pic_teardown_intr,            xlnx_pcib_msi_teardown_intr),
778         DEVMETHOD(pic_post_filter,              xlnx_pcib_msi_post_filter),
779         DEVMETHOD(pic_post_ithread,             xlnx_pcib_msi_post_ithread),
780         DEVMETHOD(pic_pre_ithread,              xlnx_pcib_msi_pre_ithread),
781
782         /* End */
783         DEVMETHOD_END
784 };
785
786 DEFINE_CLASS_1(pcib, xlnx_pcib_fdt_driver, xlnx_pcib_fdt_methods,
787     sizeof(struct xlnx_pcib_softc), generic_pcie_fdt_driver);
788
789 static devclass_t xlnx_pcib_fdt_devclass;
790
791 DRIVER_MODULE(xlnx_pcib, simplebus, xlnx_pcib_fdt_driver,
792     xlnx_pcib_fdt_devclass, 0, 0);
793 DRIVER_MODULE(xlnx_pcib, ofwbus, xlnx_pcib_fdt_driver,
794     xlnx_pcib_fdt_devclass, 0, 0);