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/pci/pci_dw.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-FreeBSD
    3  *
    4  * Copyright (c) 2019 Michal Meloun <mmel@FreeBSD.org>
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 /* Base class for all Synopsys DesignWare PCI/PCIe drivers */
   30 
   31 #include <sys/cdefs.h>
   32 __FBSDID("$FreeBSD$");
   33 
   34 #include <sys/param.h>
   35 #include <sys/systm.h>
   36 #include <sys/bus.h>
   37 #include <sys/devmap.h>
   38 #include <sys/proc.h>
   39 #include <sys/kernel.h>
   40 #include <sys/lock.h>
   41 #include <sys/malloc.h>
   42 #include <sys/module.h>
   43 #include <sys/mutex.h>
   44 #include <sys/rman.h>
   45 
   46 #include <machine/bus.h>
   47 #include <machine/intr.h>
   48 #include <machine/resource.h>
   49 
   50 #include <dev/ofw/ofw_bus.h>
   51 #include <dev/ofw/ofw_bus_subr.h>
   52 #include <dev/ofw/ofw_pci.h>
   53 #include <dev/ofw/ofwpci.h>
   54 #include <dev/pci/pcivar.h>
   55 #include <dev/pci/pcireg.h>
   56 #include <dev/pci/pcib_private.h>
   57 #include <dev/pci/pci_dw.h>
   58 
   59 #include "pcib_if.h"
   60 #include "pci_dw_if.h"
   61 
   62 #ifdef DEBUG
   63 #define debugf(fmt, args...) do { printf(fmt,##args); } while (0)
   64 #else
   65 #define debugf(fmt, args...)
   66 #endif
   67 
   68 #define DBI_WR1(sc, reg, val)   pci_dw_dbi_wr1((sc)->dev, reg, val)
   69 #define DBI_WR2(sc, reg, val)   pci_dw_dbi_wr2((sc)->dev, reg, val)
   70 #define DBI_WR4(sc, reg, val)   pci_dw_dbi_wr4((sc)->dev, reg, val)
   71 #define DBI_RD1(sc, reg)        pci_dw_dbi_rd1((sc)->dev, reg)
   72 #define DBI_RD2(sc, reg)        pci_dw_dbi_rd2((sc)->dev, reg)
   73 #define DBI_RD4(sc, reg)        pci_dw_dbi_rd4((sc)->dev, reg)
   74 
   75 #define IATU_UR_WR4(sc, reg, val)       \
   76     bus_write_4((sc)->iatu_ur_res, (sc)->iatu_ur_offset + (reg), (val))
   77 #define IATU_UR_RD4(sc, reg)            \
   78     bus_read_4((sc)->iatu_ur_res, (sc)->iatu_ur_offset + (reg))
   79 
   80 #define PCI_BUS_SHIFT           20
   81 #define PCI_SLOT_SHIFT          15
   82 #define PCI_FUNC_SHIFT          12
   83 #define PCI_BUS_MASK            0xFF
   84 #define PCI_SLOT_MASK           0x1F
   85 #define PCI_FUNC_MASK           0x07
   86 #define PCI_REG_MASK            0xFFF
   87 
   88 #define IATU_CFG_BUS(bus)       ((uint64_t)((bus)  & 0xff) << 24)
   89 #define IATU_CFG_SLOT(slot)     ((uint64_t)((slot) & 0x1f) << 19)
   90 #define IATU_CFG_FUNC(func)     ((uint64_t)((func) & 0x07) << 16)
   91 
   92 static uint32_t
   93 pci_dw_dbi_read(device_t dev, u_int reg, int width)
   94 {
   95         struct pci_dw_softc *sc;
   96 
   97         sc = device_get_softc(dev);
   98         MPASS(sc->dbi_res != NULL);
   99 
  100         switch (width) {
  101         case 4:
  102                 return (bus_read_4(sc->dbi_res, reg));
  103         case 2:
  104                 return (bus_read_2(sc->dbi_res, reg));
  105         case 1:
  106                 return (bus_read_1(sc->dbi_res, reg));
  107         default:
  108                 device_printf(sc->dev, "Unsupported width: %d\n", width);
  109                 return (0xFFFFFFFF);
  110         }
  111 }
  112 
  113 static void
  114 pci_dw_dbi_write(device_t dev, u_int reg, uint32_t val, int width)
  115 {
  116         struct pci_dw_softc *sc;
  117 
  118         sc = device_get_softc(dev);
  119         MPASS(sc->dbi_res != NULL);
  120 
  121         switch (width) {
  122         case 4:
  123                 bus_write_4(sc->dbi_res, reg, val);
  124                 break;
  125         case 2:
  126                 bus_write_2(sc->dbi_res, reg, val);
  127                 break;
  128         case 1:
  129                 bus_write_1(sc->dbi_res, reg, val);
  130                 break;
  131         default:
  132                 device_printf(sc->dev, "Unsupported width: %d\n", width);
  133                 break;
  134         }
  135 }
  136 
  137 static void
  138 pci_dw_dbi_protect(struct pci_dw_softc *sc, bool protect)
  139 {
  140         uint32_t reg;
  141 
  142         reg = DBI_RD4(sc, DW_MISC_CONTROL_1);
  143         if (protect)
  144                 reg &= ~DBI_RO_WR_EN;
  145         else
  146                 reg |= DBI_RO_WR_EN;
  147         DBI_WR4(sc, DW_MISC_CONTROL_1, reg);
  148 }
  149 
  150 static bool
  151 pci_dw_check_dev(struct pci_dw_softc *sc, u_int bus, u_int slot, u_int func,
  152     u_int reg)
  153 {
  154         bool status;
  155         int rv;
  156 
  157         if (bus < sc->bus_start || bus > sc->bus_end || slot > PCI_SLOTMAX ||
  158             func > PCI_FUNCMAX || reg > PCIE_REGMAX)
  159                 return (false);
  160 
  161         /* link is needed for access to all non-root busses */
  162         if (bus != sc->root_bus) {
  163                 rv = PCI_DW_GET_LINK(sc->dev, &status);
  164                 if (rv != 0 || !status)
  165                         return (false);
  166                 return (true);
  167         }
  168 
  169         /* we have only 1 device with 1 function root port */
  170         if (slot > 0 || func > 0)
  171                 return (false);
  172         return (true);
  173 }
  174 
  175 static bool
  176 pci_dw_detect_atu_unroll(struct pci_dw_softc *sc)
  177 {
  178         return (DBI_RD4(sc, DW_IATU_VIEWPORT) == 0xFFFFFFFFU);
  179 }
  180 
  181 static int
  182 pci_dw_detect_out_atu_regions_unroll(struct pci_dw_softc *sc)
  183 {
  184         int num_regions, i;
  185         uint32_t reg;
  186 
  187         num_regions = sc->iatu_ur_size / DW_IATU_UR_STEP;
  188 
  189         for (i = 0; i < num_regions; ++i) {
  190                 IATU_UR_WR4(sc, DW_IATU_UR_REG(i, LWR_TARGET_ADDR),
  191                     0x12340000);
  192                 reg = IATU_UR_RD4(sc, DW_IATU_UR_REG(i, LWR_TARGET_ADDR));
  193                 if (reg != 0x12340000)
  194                         break;
  195         }
  196 
  197         sc->num_out_regions = i;
  198 
  199         return (0);
  200 }
  201 
  202 static int
  203 pci_dw_detect_out_atu_regions_legacy(struct pci_dw_softc *sc)
  204 {
  205         int num_viewports, i;
  206         uint32_t reg;
  207 
  208         /* Find out how many viewports there are in total */
  209         DBI_WR4(sc, DW_IATU_VIEWPORT, IATU_REGION_INDEX(~0U));
  210         reg = DBI_RD4(sc, DW_IATU_VIEWPORT);
  211         if (reg > IATU_REGION_INDEX(~0U)) {
  212                 device_printf(sc->dev,
  213                     "Cannot detect number of output iATU regions; read %#x\n",
  214                     reg);
  215                 return (ENXIO);
  216         }
  217 
  218         num_viewports = reg + 1;
  219 
  220         /*
  221          * Find out how many of them are outbound by seeing whether a dummy
  222          * page-aligned address sticks.
  223          */
  224         for (i = 0; i < num_viewports; ++i) {
  225                 DBI_WR4(sc, DW_IATU_VIEWPORT, IATU_REGION_INDEX(i));
  226                 DBI_WR4(sc, DW_IATU_LWR_TARGET_ADDR, 0x12340000);
  227                 reg = DBI_RD4(sc, DW_IATU_LWR_TARGET_ADDR);
  228                 if (reg != 0x12340000)
  229                         break;
  230         }
  231 
  232         sc->num_out_regions = i;
  233 
  234         return (0);
  235 }
  236 
  237 static int
  238 pci_dw_detect_out_atu_regions(struct pci_dw_softc *sc)
  239 {
  240         if (sc->iatu_ur_res)
  241                 return (pci_dw_detect_out_atu_regions_unroll(sc));
  242         else
  243                 return (pci_dw_detect_out_atu_regions_legacy(sc));
  244 }
  245 
  246 static int
  247 pci_dw_map_out_atu_unroll(struct pci_dw_softc *sc, int idx, int type,
  248     uint64_t pa, uint64_t pci_addr, uint32_t size)
  249 {
  250         uint32_t reg;
  251         int i;
  252 
  253         if (size == 0)
  254                 return (0);
  255 
  256         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LWR_BASE_ADDR),
  257             pa & 0xFFFFFFFF);
  258         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, UPPER_BASE_ADDR),
  259             (pa >> 32) & 0xFFFFFFFF);
  260         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LIMIT_ADDR),
  261             (pa + size - 1) & 0xFFFFFFFF);
  262         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, LWR_TARGET_ADDR),
  263             pci_addr & 0xFFFFFFFF);
  264         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, UPPER_TARGET_ADDR),
  265             (pci_addr  >> 32) & 0xFFFFFFFF);
  266         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, CTRL1),
  267             IATU_CTRL1_TYPE(type));
  268         IATU_UR_WR4(sc, DW_IATU_UR_REG(idx, CTRL2),
  269             IATU_CTRL2_REGION_EN);
  270 
  271         /* Wait until setup becomes valid */
  272         for (i = 10; i > 0; i--) {
  273                 reg = IATU_UR_RD4(sc, DW_IATU_UR_REG(idx, CTRL2));
  274                 if (reg & IATU_CTRL2_REGION_EN)
  275                         return (0);
  276                 DELAY(5);
  277         }
  278 
  279         device_printf(sc->dev,
  280             "Cannot map outbound region %d in unroll mode iATU\n", idx);
  281         return (ETIMEDOUT);
  282 }
  283 
  284 static int
  285 pci_dw_map_out_atu_legacy(struct pci_dw_softc *sc, int idx, int type,
  286     uint64_t pa, uint64_t pci_addr, uint32_t size)
  287 {
  288         uint32_t reg;
  289         int i;
  290 
  291         if (size == 0)
  292                 return (0);
  293 
  294         DBI_WR4(sc, DW_IATU_VIEWPORT, IATU_REGION_INDEX(idx));
  295         DBI_WR4(sc, DW_IATU_LWR_BASE_ADDR, pa & 0xFFFFFFFF);
  296         DBI_WR4(sc, DW_IATU_UPPER_BASE_ADDR, (pa >> 32) & 0xFFFFFFFF);
  297         DBI_WR4(sc, DW_IATU_LIMIT_ADDR, (pa + size - 1) & 0xFFFFFFFF);
  298         DBI_WR4(sc, DW_IATU_LWR_TARGET_ADDR, pci_addr & 0xFFFFFFFF);
  299         DBI_WR4(sc, DW_IATU_UPPER_TARGET_ADDR, (pci_addr  >> 32) & 0xFFFFFFFF);
  300         DBI_WR4(sc, DW_IATU_CTRL1, IATU_CTRL1_TYPE(type));
  301         DBI_WR4(sc, DW_IATU_CTRL2, IATU_CTRL2_REGION_EN);
  302 
  303         /* Wait until setup becomes valid */
  304         for (i = 10; i > 0; i--) {
  305                 reg = DBI_RD4(sc, DW_IATU_CTRL2);
  306                 if (reg & IATU_CTRL2_REGION_EN)
  307                         return (0);
  308                 DELAY(5);
  309         }
  310 
  311         device_printf(sc->dev,
  312             "Cannot map outbound region %d in legacy mode iATU\n", idx);
  313         return (ETIMEDOUT);
  314 }
  315 
  316 /* Map one outbound ATU region */
  317 static int
  318 pci_dw_map_out_atu(struct pci_dw_softc *sc, int idx, int type,
  319     uint64_t pa, uint64_t pci_addr, uint32_t size)
  320 {
  321         if (sc->iatu_ur_res)
  322                 return (pci_dw_map_out_atu_unroll(sc, idx, type, pa,
  323                     pci_addr, size));
  324         else
  325                 return (pci_dw_map_out_atu_legacy(sc, idx, type, pa,
  326                     pci_addr, size));
  327 }
  328 
  329 static int
  330 pci_dw_setup_hw(struct pci_dw_softc *sc)
  331 {
  332         uint32_t reg;
  333         int rv, i;
  334 
  335         pci_dw_dbi_protect(sc, false);
  336 
  337         /* Setup config registers */
  338         DBI_WR1(sc, PCIR_CLASS, PCIC_BRIDGE);
  339         DBI_WR1(sc, PCIR_SUBCLASS, PCIS_BRIDGE_PCI);
  340         DBI_WR4(sc, PCIR_BAR(0), 4);
  341         DBI_WR4(sc, PCIR_BAR(1), 0);
  342         DBI_WR1(sc, PCIR_INTPIN, 1);
  343         DBI_WR1(sc, PCIR_PRIBUS_1, sc->root_bus);
  344         DBI_WR1(sc, PCIR_SECBUS_1, sc->sub_bus);
  345         DBI_WR1(sc, PCIR_SUBBUS_1, sc->bus_end);
  346         DBI_WR2(sc, PCIR_COMMAND,
  347            PCIM_CMD_PORTEN | PCIM_CMD_MEMEN |
  348            PCIM_CMD_BUSMASTEREN | PCIM_CMD_SERRESPEN);
  349         pci_dw_dbi_protect(sc, true);
  350 
  351         /* Setup outbound memory windows */
  352         for (i = 0; i < min(sc->num_mem_ranges, sc->num_out_regions - 1); ++i) {
  353                 rv = pci_dw_map_out_atu(sc, i + 1, IATU_CTRL1_TYPE_MEM,
  354                     sc->mem_ranges[i].host, sc->mem_ranges[i].pci,
  355                     sc->mem_ranges[i].size);
  356                 if (rv != 0)
  357                         return (rv);
  358         }
  359 
  360         /* If we have enough regions ... */
  361         if (sc->num_mem_ranges + 1 < sc->num_out_regions &&
  362             sc->io_range.size != 0) {
  363                 /* Setup outbound I/O window */
  364                 rv = pci_dw_map_out_atu(sc, sc->num_mem_ranges + 1,
  365                     IATU_CTRL1_TYPE_IO, sc->io_range.host, sc->io_range.pci,
  366                     sc->io_range.size);
  367                 if (rv != 0)
  368                         return (rv);
  369         }
  370 
  371         /* Adjust number of lanes */
  372         reg = DBI_RD4(sc, DW_PORT_LINK_CTRL);
  373         reg &= ~PORT_LINK_CAPABLE(~0);
  374         switch (sc->num_lanes) {
  375         case 1:
  376                 reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_1);
  377                 break;
  378         case 2:
  379                 reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_2);
  380                 break;
  381         case 4:
  382                 reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_4);
  383                 break;
  384         case 8:
  385                 reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_8);
  386                 break;
  387         case 16:
  388                 reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_16);
  389                 break;
  390         case 32:
  391                 reg |= PORT_LINK_CAPABLE(PORT_LINK_CAPABLE_32);
  392                 break;
  393         default:
  394                 device_printf(sc->dev,
  395                     "'num-lanes' property have invalid value: %d\n",
  396                     sc->num_lanes);
  397                 return (EINVAL);
  398         }
  399         DBI_WR4(sc, DW_PORT_LINK_CTRL, reg);
  400 
  401         /* And link width */
  402         reg = DBI_RD4(sc, DW_GEN2_CTRL);
  403         reg &= ~GEN2_CTRL_NUM_OF_LANES(~0);
  404         switch (sc->num_lanes) {
  405         case 1:
  406                 reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_1);
  407                 break;
  408         case 2:
  409                 reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_2);
  410                 break;
  411         case 4:
  412                 reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_4);
  413                 break;
  414         case 8:
  415                 reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_8);
  416                 break;
  417         case 16:
  418                 reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_16);
  419                 break;
  420         case 32:
  421                 reg |= GEN2_CTRL_NUM_OF_LANES(GEN2_CTRL_NUM_OF_LANES_32);
  422                 break;
  423         }
  424         DBI_WR4(sc, DW_GEN2_CTRL, reg);
  425 
  426         reg = DBI_RD4(sc, DW_GEN2_CTRL);
  427         reg |= DIRECT_SPEED_CHANGE;
  428         DBI_WR4(sc, DW_GEN2_CTRL, reg);
  429 
  430         return (0);
  431 }
  432 
  433 static int
  434 pci_dw_decode_ranges(struct pci_dw_softc *sc, struct ofw_pci_range *ranges,
  435      int nranges)
  436 {
  437         int i, nmem, rv;
  438 
  439         nmem = 0;
  440         for (i = 0; i < nranges; i++) {
  441                 if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
  442                     OFW_PCI_PHYS_HI_SPACE_MEM32)
  443                         ++nmem;
  444         }
  445 
  446         sc->mem_ranges = malloc(nmem * sizeof(*sc->mem_ranges), M_DEVBUF,
  447             M_WAITOK);
  448         sc->num_mem_ranges = nmem;
  449 
  450         nmem = 0;
  451         for (i = 0; i < nranges; i++) {
  452                 if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK)  ==
  453                     OFW_PCI_PHYS_HI_SPACE_IO) {
  454                         if (sc->io_range.size != 0) {
  455                                 device_printf(sc->dev,
  456                                     "Duplicated IO range found in DT\n");
  457                                 rv = ENXIO;
  458                                 goto out;
  459                         }
  460 
  461                         sc->io_range = ranges[i];
  462                         if (sc->io_range.size > UINT32_MAX) {
  463                                 device_printf(sc->dev,
  464                                     "ATU IO window size is too large. "
  465                                     "Up to 4GB windows are supported, "
  466                                     "trimming window size to 4GB\n");
  467                                 sc->io_range.size = UINT32_MAX;
  468                         }
  469                 }
  470                 if ((ranges[i].pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) ==
  471                     OFW_PCI_PHYS_HI_SPACE_MEM32) {
  472                         MPASS(nmem < sc->num_mem_ranges);
  473                         sc->mem_ranges[nmem] = ranges[i];
  474                         if (sc->mem_ranges[nmem].size > UINT32_MAX) {
  475                                 device_printf(sc->dev,
  476                                     "ATU MEM window size is too large. "
  477                                     "Up to 4GB windows are supported, "
  478                                     "trimming window size to 4GB\n");
  479                                 sc->mem_ranges[nmem].size = UINT32_MAX;
  480                         }
  481                         ++nmem;
  482                 }
  483         }
  484 
  485         MPASS(nmem == sc->num_mem_ranges);
  486 
  487         if (nmem == 0) {
  488                 device_printf(sc->dev,
  489                     "Missing required memory range in DT\n");
  490                 return (ENXIO);
  491         }
  492 
  493         return (0);
  494 
  495 out:
  496         free(sc->mem_ranges, M_DEVBUF);
  497         return (rv);
  498 }
  499 
  500 /*-----------------------------------------------------------------------------
  501  *
  502  *  P C I B   I N T E R F A C E
  503  */
  504 
  505 static uint32_t
  506 pci_dw_read_config(device_t dev, u_int bus, u_int slot,
  507     u_int func, u_int reg, int bytes)
  508 {
  509         struct pci_dw_softc *sc;
  510         struct resource *res;
  511         uint32_t data;
  512         uint64_t addr;
  513         int type, rv;
  514 
  515         sc = device_get_softc(dev);
  516 
  517         if (!pci_dw_check_dev(sc, bus, slot, func, reg))
  518                 return (0xFFFFFFFFU);
  519 
  520         if (bus == sc->root_bus) {
  521                 res = (sc->dbi_res);
  522         } else {
  523                 addr = IATU_CFG_BUS(bus) | IATU_CFG_SLOT(slot) |
  524                     IATU_CFG_FUNC(func);
  525                 if (bus == sc->sub_bus)
  526                         type = IATU_CTRL1_TYPE_CFG0;
  527                 else
  528                         type = IATU_CTRL1_TYPE_CFG1;
  529                 rv = pci_dw_map_out_atu(sc, 0, type,
  530                     sc->cfg_pa, addr, sc->cfg_size);
  531                 if (rv != 0)
  532                         return (0xFFFFFFFFU);
  533                 res = sc->cfg_res;
  534         }
  535 
  536         switch (bytes) {
  537         case 1:
  538                 data = bus_read_1(res, reg);
  539                 break;
  540         case 2:
  541                 data = bus_read_2(res, reg);
  542                 break;
  543         case 4:
  544                 data = bus_read_4(res, reg);
  545                 break;
  546         default:
  547                 data =  0xFFFFFFFFU;
  548         }
  549 
  550         return (data);
  551 
  552 }
  553 
  554 static void
  555 pci_dw_write_config(device_t dev, u_int bus, u_int slot,
  556     u_int func, u_int reg, uint32_t val, int bytes)
  557 {
  558         struct pci_dw_softc *sc;
  559         struct resource *res;
  560         uint64_t addr;
  561         int type, rv;
  562 
  563         sc = device_get_softc(dev);
  564         if (!pci_dw_check_dev(sc, bus, slot, func, reg))
  565                 return;
  566 
  567         if (bus == sc->root_bus) {
  568                 res = (sc->dbi_res);
  569         } else {
  570                 addr = IATU_CFG_BUS(bus) | IATU_CFG_SLOT(slot) |
  571                     IATU_CFG_FUNC(func);
  572                 if (bus == sc->sub_bus)
  573                         type = IATU_CTRL1_TYPE_CFG0;
  574                 else
  575                         type = IATU_CTRL1_TYPE_CFG1;
  576                 rv = pci_dw_map_out_atu(sc, 0, type,
  577                     sc->cfg_pa, addr, sc->cfg_size);
  578                 if (rv != 0)
  579                         return ;
  580                 res = sc->cfg_res;
  581         }
  582 
  583         switch (bytes) {
  584         case 1:
  585                 bus_write_1(res, reg, val);
  586                 break;
  587         case 2:
  588                 bus_write_2(res, reg, val);
  589                 break;
  590         case 4:
  591                 bus_write_4(res, reg, val);
  592                 break;
  593         default:
  594                 break;
  595         }
  596 }
  597 
  598 static int
  599 pci_dw_alloc_msi(device_t pci, device_t child, int count,
  600     int maxcount, int *irqs)
  601 {
  602         phandle_t msi_parent;
  603         int rv;
  604 
  605         rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
  606             &msi_parent, NULL);
  607         if (rv != 0)
  608                 return (rv);
  609 
  610         return (intr_alloc_msi(pci, child, msi_parent, count, maxcount,
  611             irqs));
  612 }
  613 
  614 static int
  615 pci_dw_release_msi(device_t pci, device_t child, int count, int *irqs)
  616 {
  617         phandle_t msi_parent;
  618         int rv;
  619 
  620         rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
  621             &msi_parent, NULL);
  622         if (rv != 0)
  623                 return (rv);
  624         return (intr_release_msi(pci, child, msi_parent, count, irqs));
  625 }
  626 
  627 static int
  628 pci_dw_map_msi(device_t pci, device_t child, int irq, uint64_t *addr,
  629     uint32_t *data)
  630 {
  631         phandle_t msi_parent;
  632         int rv;
  633 
  634         rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
  635             &msi_parent, NULL);
  636         if (rv != 0)
  637                 return (rv);
  638 
  639         return (intr_map_msi(pci, child, msi_parent, irq, addr, data));
  640 }
  641 
  642 static int
  643 pci_dw_alloc_msix(device_t pci, device_t child, int *irq)
  644 {
  645         phandle_t msi_parent;
  646         int rv;
  647 
  648         rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
  649             &msi_parent, NULL);
  650         if (rv != 0)
  651                 return (rv);
  652         return (intr_alloc_msix(pci, child, msi_parent, irq));
  653 }
  654 
  655 static int
  656 pci_dw_release_msix(device_t pci, device_t child, int irq)
  657 {
  658         phandle_t msi_parent;
  659         int rv;
  660 
  661         rv = ofw_bus_msimap(ofw_bus_get_node(pci), pci_get_rid(child),
  662             &msi_parent, NULL);
  663         if (rv != 0)
  664                 return (rv);
  665         return (intr_release_msix(pci, child, msi_parent, irq));
  666 }
  667 
  668 static int
  669 pci_dw_get_id(device_t pci, device_t child, enum pci_id_type type,
  670     uintptr_t *id)
  671 {
  672         phandle_t node;
  673         int rv;
  674         uint32_t rid;
  675         uint16_t pci_rid;
  676 
  677         if (type != PCI_ID_MSI)
  678                 return (pcib_get_id(pci, child, type, id));
  679 
  680         node = ofw_bus_get_node(pci);
  681         pci_rid = pci_get_rid(child);
  682 
  683         rv = ofw_bus_msimap(node, pci_rid, NULL, &rid);
  684         if (rv != 0)
  685                 return (rv);
  686         *id = rid;
  687 
  688         return (0);
  689 }
  690 
  691 /*-----------------------------------------------------------------------------
  692  *
  693  *  B U S  / D E V I C E   I N T E R F A C E
  694  */
  695 static bus_dma_tag_t
  696 pci_dw_get_dma_tag(device_t dev, device_t child)
  697 {
  698         struct pci_dw_softc *sc;
  699 
  700         sc = device_get_softc(dev);
  701         return (sc->dmat);
  702 }
  703 
  704 int
  705 pci_dw_init(device_t dev)
  706 {
  707         struct pci_dw_softc *sc;
  708         int rv, rid;
  709         bool unroll_mode;
  710 
  711         sc = device_get_softc(dev);
  712         sc->dev = dev;
  713         sc->node = ofw_bus_get_node(dev);
  714 
  715         mtx_init(&sc->mtx, "pci_dw_mtx", NULL, MTX_DEF);
  716 
  717         /* XXXn Should not be this configurable ? */
  718         sc->bus_start = 0;
  719         sc->bus_end = 255;
  720         sc->root_bus = 0;
  721         sc->sub_bus = 1;
  722 
  723         /* Read FDT properties */
  724         if (!sc->coherent)
  725                 sc->coherent = OF_hasprop(sc->node, "dma-coherent");
  726 
  727         rv = OF_getencprop(sc->node, "num-lanes", &sc->num_lanes,
  728             sizeof(sc->num_lanes));
  729         if (rv != sizeof(sc->num_lanes))
  730                 sc->num_lanes = 1;
  731         if (sc->num_lanes != 1 && sc->num_lanes != 2 &&
  732             sc->num_lanes != 4 && sc->num_lanes != 8) {
  733                 device_printf(dev,
  734                     "invalid number of lanes: %d\n",sc->num_lanes);
  735                 sc->num_lanes = 0;
  736                 rv = ENXIO;
  737                 goto out;
  738         }
  739 
  740         rid = 0;
  741         rv = ofw_bus_find_string_index(sc->node, "reg-names", "config", &rid);
  742         if (rv != 0) {
  743                 device_printf(dev, "Cannot get config space memory\n");
  744                 rv = ENXIO;
  745                 goto out;
  746         }
  747         sc->cfg_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid,
  748             RF_ACTIVE);
  749         if (sc->cfg_res == NULL) {
  750                 device_printf(dev, "Cannot allocate config space(rid: %d)\n",
  751                     rid);
  752                 rv = ENXIO;
  753                 goto out;
  754         }
  755 
  756         /* Fill up config region related variables */
  757         sc->cfg_size = rman_get_size(sc->cfg_res);
  758         sc->cfg_pa = rman_get_start(sc->cfg_res) ;
  759 
  760         if (bootverbose)
  761                 device_printf(dev, "Bus is%s cache-coherent\n",
  762                     sc->coherent ? "" : " not");
  763         rv = bus_dma_tag_create(bus_get_dma_tag(dev), /* parent */
  764             1, 0,                               /* alignment, bounds */
  765             BUS_SPACE_MAXADDR,                  /* lowaddr */
  766             BUS_SPACE_MAXADDR,                  /* highaddr */
  767             NULL, NULL,                         /* filter, filterarg */
  768             BUS_SPACE_MAXSIZE,                  /* maxsize */
  769             BUS_SPACE_UNRESTRICTED,             /* nsegments */
  770             BUS_SPACE_MAXSIZE,                  /* maxsegsize */
  771             sc->coherent ? BUS_DMA_COHERENT : 0, /* flags */
  772             NULL, NULL,                         /* lockfunc, lockarg */
  773             &sc->dmat);
  774         if (rv != 0)
  775                 goto out;
  776 
  777         rv = ofw_pcib_init(dev);
  778         if (rv != 0)
  779                 goto out;
  780         rv = pci_dw_decode_ranges(sc, sc->ofw_pci.sc_range,
  781             sc->ofw_pci.sc_nrange);
  782         if (rv != 0)
  783                 goto out;
  784 
  785         unroll_mode = pci_dw_detect_atu_unroll(sc);
  786         if (bootverbose)
  787                 device_printf(dev, "Using iATU %s mode\n",
  788                     unroll_mode ? "unroll" : "legacy");
  789         if (unroll_mode) {
  790                 rid = 0;
  791                 rv = ofw_bus_find_string_index(sc->node, "reg-names", "atu", &rid);
  792                 if (rv == 0) {
  793                         sc->iatu_ur_res = bus_alloc_resource_any(dev,
  794                             SYS_RES_MEMORY, &rid, RF_ACTIVE);
  795                         if (sc->iatu_ur_res == NULL) {
  796                                 device_printf(dev,
  797                                     "Cannot allocate iATU space (rid: %d)\n",
  798                                     rid);
  799                                 rv = ENXIO;
  800                                 goto out;
  801                         }
  802                         sc->iatu_ur_offset = 0;
  803                         sc->iatu_ur_size = rman_get_size(sc->iatu_ur_res);
  804                 } else if (rv == ENOENT) {
  805                         sc->iatu_ur_res = sc->dbi_res;
  806                         sc->iatu_ur_offset = DW_DEFAULT_IATU_UR_DBI_OFFSET;
  807                         sc->iatu_ur_size = DW_DEFAULT_IATU_UR_DBI_SIZE;
  808                 } else {
  809                         device_printf(dev, "Cannot get iATU space memory\n");
  810                         rv = ENXIO;
  811                         goto out;
  812                 }
  813         }
  814 
  815         rv = pci_dw_detect_out_atu_regions(sc);
  816         if (rv != 0)
  817                 goto out;
  818 
  819         if (bootverbose)
  820                 device_printf(sc->dev, "Detected outbound iATU regions: %d\n",
  821                     sc->num_out_regions);
  822 
  823         rv = pci_dw_setup_hw(sc);
  824         if (rv != 0)
  825                 goto out;
  826 
  827         device_add_child(dev, "pci", -1);
  828 
  829         return (0);
  830 out:
  831         /* XXX Cleanup */
  832         return (rv);
  833 }
  834 
  835 static device_method_t pci_dw_methods[] = {
  836         /* Bus interface */
  837         DEVMETHOD(bus_get_dma_tag,      pci_dw_get_dma_tag),
  838 
  839         /* pcib interface */
  840         DEVMETHOD(pcib_read_config,     pci_dw_read_config),
  841         DEVMETHOD(pcib_write_config,    pci_dw_write_config),
  842         DEVMETHOD(pcib_alloc_msi,       pci_dw_alloc_msi),
  843         DEVMETHOD(pcib_release_msi,     pci_dw_release_msi),
  844         DEVMETHOD(pcib_alloc_msix,      pci_dw_alloc_msix),
  845         DEVMETHOD(pcib_release_msix,    pci_dw_release_msix),
  846         DEVMETHOD(pcib_map_msi,         pci_dw_map_msi),
  847         DEVMETHOD(pcib_get_id,          pci_dw_get_id),
  848 
  849         /* OFW bus interface */
  850         DEVMETHOD(ofw_bus_get_compat,   ofw_bus_gen_get_compat),
  851         DEVMETHOD(ofw_bus_get_model,    ofw_bus_gen_get_model),
  852         DEVMETHOD(ofw_bus_get_name,     ofw_bus_gen_get_name),
  853         DEVMETHOD(ofw_bus_get_node,     ofw_bus_gen_get_node),
  854         DEVMETHOD(ofw_bus_get_type,     ofw_bus_gen_get_type),
  855 
  856         /* PCI DW interface  */
  857         DEVMETHOD(pci_dw_dbi_read,      pci_dw_dbi_read),
  858         DEVMETHOD(pci_dw_dbi_write,     pci_dw_dbi_write),
  859         DEVMETHOD_END
  860 };
  861 
  862 DEFINE_CLASS_1(pcib, pci_dw_driver, pci_dw_methods,
  863     sizeof(struct pci_dw_softc), ofw_pcib_driver);

Cache object: 60c68a1954880d78ad2b47897c0d7ace


[ 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.