The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/xilinx/xlnx_pcib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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_fdt_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                 /* Assume the range is valid. */
  600                 found = true;
  601 
  602                 /* Check this range is valid. */
  603                 for (end_irq = irq; end_irq < irq + count; end_irq++) {
  604                         if (sc->isrcs[end_irq].flags & XLNX_IRQ_FLAG_USED) {
  605                                 /* This is already used. */
  606                                 found = false;
  607                                 break;
  608                         }
  609                 }
  610 
  611                 if (found)
  612                         break;
  613         }
  614 
  615         if (!found || irq == (XLNX_PCIB_MAX_MSI - 1)) {
  616                 /* Not enough interrupts were found. */
  617                 mtx_unlock(&sc->mtx);
  618                 return (ENXIO);
  619         }
  620 
  621         /* Mark the interrupt as used. */
  622         for (i = 0; i < count; i++)
  623                 sc->isrcs[irq + i].flags |= XLNX_IRQ_FLAG_USED;
  624 
  625         mtx_unlock(&sc->mtx);
  626 
  627         for (i = 0; i < count; i++)
  628                 srcs[i] = (struct intr_irqsrc *)&sc->isrcs[irq + i];
  629 
  630         *pic = device_get_parent(dev);
  631 
  632         return (0);
  633 }
  634 
  635 static int
  636 xlnx_pcib_msi_release_msi(device_t dev, device_t child, int count,
  637     struct intr_irqsrc **isrc)
  638 {
  639         struct xlnx_pcib_softc *sc;
  640         struct xlnx_pcib_irqsrc *xi;
  641         int i;
  642 
  643         sc = device_get_softc(dev);
  644         mtx_lock(&sc->mtx);
  645         for (i = 0; i < count; i++) {
  646                 xi = (struct xlnx_pcib_irqsrc *)isrc[i];
  647 
  648                 KASSERT(xi->flags & XLNX_IRQ_FLAG_USED,
  649                     ("%s: Releasing an unused MSI interrupt", __func__));
  650 
  651                 xi->flags &= ~XLNX_IRQ_FLAG_USED;
  652         }
  653 
  654         mtx_unlock(&sc->mtx);
  655         return (0);
  656 }
  657 
  658 static int
  659 xlnx_pcib_msi_map_msi(device_t dev, device_t child, struct intr_irqsrc *isrc,
  660     uint64_t *addr, uint32_t *data)
  661 {
  662         struct xlnx_pcib_softc *sc;
  663         struct xlnx_pcib_irqsrc *xi;
  664 
  665         sc = device_get_softc(dev);
  666         xi = (struct xlnx_pcib_irqsrc *)isrc;
  667 
  668         *addr = vtophys(sc->msi_page);
  669         *data = xi->irq;
  670 
  671         return (0);
  672 }
  673 
  674 static void
  675 xlnx_pcib_msi_mask(device_t dev, struct intr_irqsrc *isrc, bool mask)
  676 {
  677         struct generic_pcie_fdt_softc *fdt_sc;
  678         struct generic_pcie_core_softc *sc;
  679         struct xlnx_pcib_softc *xlnx_sc;
  680         struct xlnx_pcib_irqsrc *xi;
  681         uint32_t msireg, irq;
  682         uint32_t reg;
  683 
  684         xlnx_sc = device_get_softc(dev);
  685         fdt_sc = &xlnx_sc->fdt_sc;
  686         sc = &fdt_sc->base;
  687 
  688         xi = (struct xlnx_pcib_irqsrc *)isrc;
  689 
  690         irq = xi->irq;
  691         if (irq < 32)
  692                 msireg = XLNX_PCIE_RPMSIID1_MASK;
  693         else
  694                 msireg = XLNX_PCIE_RPMSIID2_MASK;
  695 
  696         reg = bus_read_4(sc->res, msireg);
  697         if (mask)
  698                 reg &= ~(1 << irq);
  699         else
  700                 reg |= (1 << irq);
  701         bus_write_4(sc->res, msireg, reg);
  702 }
  703 
  704 static void
  705 xlnx_pcib_msi_disable_intr(device_t dev, struct intr_irqsrc *isrc)
  706 {
  707 
  708         xlnx_pcib_msi_mask(dev, isrc, true);
  709 }
  710 
  711 static void
  712 xlnx_pcib_msi_enable_intr(device_t dev, struct intr_irqsrc *isrc)
  713 {
  714 
  715         xlnx_pcib_msi_mask(dev, isrc, false);
  716 }
  717 
  718 static void
  719 xlnx_pcib_msi_post_filter(device_t dev, struct intr_irqsrc *isrc)
  720 {
  721 
  722 }
  723 
  724 static void
  725 xlnx_pcib_msi_post_ithread(device_t dev, struct intr_irqsrc *isrc)
  726 {
  727 
  728         xlnx_pcib_msi_mask(dev, isrc, false);
  729 }
  730 
  731 static void
  732 xlnx_pcib_msi_pre_ithread(device_t dev, struct intr_irqsrc *isrc)
  733 {
  734 
  735         xlnx_pcib_msi_mask(dev, isrc, true);
  736 }
  737 
  738 static int
  739 xlnx_pcib_msi_setup_intr(device_t dev, struct intr_irqsrc *isrc,
  740     struct resource *res, struct intr_map_data *data)
  741 {
  742 
  743         return (0);
  744 }
  745 
  746 static int
  747 xlnx_pcib_msi_teardown_intr(device_t dev, struct intr_irqsrc *isrc,
  748     struct resource *res, struct intr_map_data *data)
  749 {
  750 
  751         return (0);
  752 }
  753 
  754 static device_method_t xlnx_pcib_fdt_methods[] = {
  755         /* Device interface */
  756         DEVMETHOD(device_probe,         xlnx_pcib_fdt_probe),
  757         DEVMETHOD(device_attach,        xlnx_pcib_fdt_attach),
  758 
  759         /* pcib interface */
  760         DEVMETHOD(pcib_get_id,          xlnx_pcib_fdt_get_id),
  761         DEVMETHOD(pcib_read_config,     xlnx_pcib_read_config),
  762         DEVMETHOD(pcib_write_config,    xlnx_pcib_write_config),
  763         DEVMETHOD(pcib_alloc_msi,       xlnx_pcib_alloc_msi),
  764         DEVMETHOD(pcib_release_msi,     xlnx_pcib_release_msi),
  765         DEVMETHOD(pcib_map_msi,         xlnx_pcib_map_msi),
  766 
  767         /* MSI interface */
  768         DEVMETHOD(msi_alloc_msi,                xlnx_pcib_msi_alloc_msi),
  769         DEVMETHOD(msi_release_msi,              xlnx_pcib_msi_release_msi),
  770         DEVMETHOD(msi_map_msi,                  xlnx_pcib_msi_map_msi),
  771 
  772         /* Interrupt controller interface */
  773         DEVMETHOD(pic_disable_intr,             xlnx_pcib_msi_disable_intr),
  774         DEVMETHOD(pic_enable_intr,              xlnx_pcib_msi_enable_intr),
  775         DEVMETHOD(pic_setup_intr,               xlnx_pcib_msi_setup_intr),
  776         DEVMETHOD(pic_teardown_intr,            xlnx_pcib_msi_teardown_intr),
  777         DEVMETHOD(pic_post_filter,              xlnx_pcib_msi_post_filter),
  778         DEVMETHOD(pic_post_ithread,             xlnx_pcib_msi_post_ithread),
  779         DEVMETHOD(pic_pre_ithread,              xlnx_pcib_msi_pre_ithread),
  780 
  781         /* End */
  782         DEVMETHOD_END
  783 };
  784 
  785 DEFINE_CLASS_1(pcib, xlnx_pcib_fdt_driver, xlnx_pcib_fdt_methods,
  786     sizeof(struct xlnx_pcib_softc), generic_pcie_fdt_driver);
  787 
  788 DRIVER_MODULE(xlnx_pcib, simplebus, xlnx_pcib_fdt_driver, 0, 0);
  789 DRIVER_MODULE(xlnx_pcib, ofwbus, xlnx_pcib_fdt_driver, 0, 0);

Cache object: df8a425325b60c4b87fe710a4eaea8e6


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.