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/bhnd/bhndb/bhndb_pci.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  * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
    3  * Copyright (c) 2017 The FreeBSD Foundation
    4  * All rights reserved.
    5  *
    6  * Portions of this software were developed by Landon Fuller
    7  * under sponsorship from the FreeBSD Foundation.
    8  *
    9  * Redistribution and use in source and binary forms, with or without
   10  * modification, are permitted provided that the following conditions
   11  * are met:
   12  * 1. Redistributions of source code must retain the above copyright
   13  *    notice, this list of conditions and the following disclaimer,
   14  *    without modification.
   15  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
   16  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
   17  *    redistribution must be conditioned upon including a substantially
   18  *    similar Disclaimer requirement for further binary redistribution.
   19  *
   20  * NO WARRANTY
   21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
   23  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
   24  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
   25  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
   26  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
   29  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   31  * THE POSSIBILITY OF SUCH DAMAGES.
   32  */
   33 
   34 #include <sys/cdefs.h>
   35 __FBSDID("$FreeBSD$");
   36 
   37 /*
   38  * PCI-specific implementation for the BHNDB bridge driver.
   39  * 
   40  * Provides support for bridging from a PCI parent bus to a BHND-compatible
   41  * bus (e.g. bcma or siba) via a Broadcom PCI core configured in end-point
   42  * mode.
   43  * 
   44  * This driver handles all initial generic host-level PCI interactions with a
   45  * PCI/PCIe bridge core operating in endpoint mode. Once the bridged bhnd(4)
   46  * bus has been enumerated, this driver works in tandem with a core-specific
   47  * bhnd_pci_hostb driver to manage the PCI core.
   48  */
   49 
   50 #include <sys/param.h>
   51 #include <sys/kernel.h>
   52 #include <sys/bus.h>
   53 #include <sys/limits.h>
   54 #include <sys/malloc.h>
   55 #include <sys/module.h>
   56 #include <sys/systm.h>
   57 
   58 #include <dev/pci/pcireg.h>
   59 #include <dev/pci/pcivar.h>
   60 
   61 #include <dev/bhnd/bhnd.h>
   62 #include <dev/bhnd/bhndreg.h>
   63 
   64 #include <dev/bhnd/bhnd_erom.h>
   65 #include <dev/bhnd/bhnd_eromvar.h>
   66 
   67 #include <dev/bhnd/siba/sibareg.h>
   68 
   69 #include <dev/bhnd/cores/pci/bhnd_pcireg.h>
   70 
   71 #include "bhnd_pwrctl_hostb_if.h"
   72 
   73 #include "bhndb_pcireg.h"
   74 #include "bhndb_pcivar.h"
   75 #include "bhndb_private.h"
   76 
   77 struct bhndb_pci_eio;
   78 struct bhndb_pci_probe;
   79 
   80 static int              bhndb_pci_alloc_msi(struct bhndb_pci_softc *sc,
   81                             int *msi_count);
   82 
   83 static int              bhndb_pci_add_children(struct bhndb_pci_softc *sc);
   84 
   85 static bhnd_devclass_t  bhndb_expected_pci_devclass(device_t dev);
   86 static bool             bhndb_is_pcie_attached(device_t dev);
   87 
   88 static int              bhndb_enable_pci_clocks(device_t dev);
   89 static int              bhndb_disable_pci_clocks(device_t dev);
   90 
   91 static int              bhndb_pci_compat_setregwin(device_t dev,
   92                             device_t pci_dev, const struct bhndb_regwin *,
   93                             bhnd_addr_t);
   94 static int              bhndb_pci_fast_setregwin(device_t dev, device_t pci_dev,
   95                             const struct bhndb_regwin *, bhnd_addr_t);
   96 
   97 static void             bhndb_pci_write_core(struct bhndb_pci_softc *sc,
   98                             bus_size_t offset, uint32_t value, u_int width);
   99 static uint32_t         bhndb_pci_read_core(struct bhndb_pci_softc *sc,
  100                             bus_size_t offset, u_int width);
  101 
  102 static int              bhndb_pci_srsh_pi_war(struct bhndb_pci_softc *sc,
  103                             struct bhndb_pci_probe *probe);
  104 
  105 static bus_addr_t       bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc);
  106 static bus_size_t       bhndb_pci_sprom_size(struct bhndb_pci_softc *sc);
  107 
  108 static int              bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe,
  109                             device_t dev, bhnd_devclass_t pci_devclass);
  110 static void             bhndb_pci_probe_free(struct bhndb_pci_probe *probe);
  111 
  112 static int              bhndb_pci_probe_copy_core_table(
  113                             struct bhndb_pci_probe *probe,
  114                             struct bhnd_core_info **cores, u_int *ncores);
  115 static void             bhndb_pci_probe_free_core_table(
  116                             struct bhnd_core_info *cores);
  117 
  118 static void             bhndb_pci_probe_write(struct bhndb_pci_probe *sc,
  119                             bhnd_addr_t addr, bhnd_size_t offset,
  120                             uint32_t value, u_int width);
  121 static uint32_t         bhndb_pci_probe_read(struct bhndb_pci_probe *sc,
  122                             bhnd_addr_t addr, bhnd_size_t offset, u_int width);
  123 
  124 static void             bhndb_pci_eio_init(struct bhndb_pci_eio *eio,
  125                             struct bhndb_pci_probe *probe);
  126 static int              bhndb_pci_eio_map(struct bhnd_erom_io *eio,
  127                             bhnd_addr_t addr, bhnd_size_t size);
  128 static int              bhndb_pci_eio_tell(struct bhnd_erom_io *eio,
  129                             bhnd_addr_t *addr, bhnd_size_t *size);
  130 static uint32_t         bhndb_pci_eio_read(struct bhnd_erom_io *eio,
  131                             bhnd_size_t offset, u_int width);
  132 
  133 #define BHNDB_PCI_MSI_COUNT     1
  134 
  135 static struct bhndb_pci_quirk   bhndb_pci_quirks[];
  136 static struct bhndb_pci_quirk   bhndb_pcie_quirks[];
  137 static struct bhndb_pci_quirk   bhndb_pcie2_quirks[];
  138 
  139 static struct bhndb_pci_core bhndb_pci_cores[] = {
  140         BHNDB_PCI_CORE(PCI,     bhndb_pci_quirks),
  141         BHNDB_PCI_CORE(PCIE,    bhndb_pcie_quirks),
  142         BHNDB_PCI_CORE(PCIE2,   bhndb_pcie2_quirks),
  143         BHNDB_PCI_CORE_END
  144 };
  145 
  146 /* bhndb_pci erom I/O instance state */
  147 struct bhndb_pci_eio {
  148         struct bhnd_erom_io              eio;
  149         bool                             mapped;        /**< true if a valid mapping exists */
  150         bhnd_addr_t                      addr;          /**< mapped address */
  151         bhnd_size_t                      size;          /**< mapped size */
  152         struct bhndb_pci_probe          *probe;         /**< borrowed probe reference */
  153 };
  154 
  155 /**
  156  * Provides early bus access to the bridged device's cores and core enumeration
  157  * table.
  158  *
  159  * May be safely used during probe or early device attach, prior to calling
  160  * bhndb_attach().
  161  */
  162 struct bhndb_pci_probe {
  163         device_t                         dev;           /**< bridge device */
  164         device_t                         pci_dev;       /**< parent PCI device */
  165         struct bhnd_chipid               cid;           /**< chip identification */
  166         struct bhnd_core_info            hostb_core;    /**< PCI bridge core info */
  167 
  168         struct bhndb_pci_eio             erom_io;       /**< erom I/O instance */
  169         bhnd_erom_class_t               *erom_class;    /**< probed erom class */
  170         bhnd_erom_t                     *erom;          /**< erom parser */
  171         struct bhnd_core_info           *cores;         /**< erom-owned core table */
  172         u_int                            ncores;        /**< number of cores */
  173 
  174         const struct bhndb_regwin       *m_win;         /**< mapped register window, or NULL if no mapping */
  175         struct resource                 *m_res;         /**< resource containing the register window, or NULL if no window mapped */
  176         bhnd_addr_t                      m_target;      /**< base address mapped by m_win */
  177         bhnd_addr_t                      m_addr;        /**< mapped address */
  178         bhnd_size_t                      m_size;        /**< mapped size */
  179         bool                             m_valid;       /**< true if a valid mapping exists, false otherwise */
  180 
  181         struct bhndb_host_resources     *hr;            /**< backing host resources */
  182 };
  183 
  184 static struct bhndb_pci_quirk bhndb_pci_quirks[] = {
  185         /* Backplane interrupt flags must be routed via siba-specific
  186          * SIBA_CFG0_INTVEC configuration register; the BHNDB_PCI_INT_MASK
  187          * PCI configuration register is unsupported. */
  188         {{ BHND_MATCH_CHIP_TYPE         (SIBA) },
  189          { BHND_MATCH_CORE_REV          (HWREV_LTE(5)) },
  190                 BHNDB_PCI_QUIRK_SIBA_INTVEC },
  191 
  192         /* All PCI core revisions require the SRSH work-around */
  193         BHNDB_PCI_QUIRK(HWREV_ANY,      BHNDB_PCI_QUIRK_SRSH_WAR),
  194         BHNDB_PCI_QUIRK_END
  195 };
  196 
  197 static struct bhndb_pci_quirk bhndb_pcie_quirks[] = {
  198         /* All PCIe-G1 core revisions require the SRSH work-around */
  199         BHNDB_PCI_QUIRK(HWREV_ANY,      BHNDB_PCI_QUIRK_SRSH_WAR),
  200         BHNDB_PCI_QUIRK_END
  201 };
  202 
  203 static struct bhndb_pci_quirk bhndb_pcie2_quirks[] = {
  204         BHNDB_PCI_QUIRK_END
  205 };
  206 
  207 /**
  208  * Return the device table entry for @p ci, or NULL if none.
  209  */
  210 static struct bhndb_pci_core *
  211 bhndb_pci_find_core(struct bhnd_core_info *ci)
  212 {
  213         for (size_t i = 0; !BHNDB_PCI_IS_CORE_END(&bhndb_pci_cores[i]); i++) {
  214                 struct bhndb_pci_core *entry = &bhndb_pci_cores[i];
  215 
  216                 if (bhnd_core_matches(ci, &entry->match))
  217                         return (entry);
  218         }
  219 
  220         return (NULL);
  221 }
  222 
  223 /**
  224  * Return all quirk flags for the given @p cid and @p ci.
  225  */
  226 static uint32_t
  227 bhndb_pci_get_core_quirks(struct bhnd_chipid *cid, struct bhnd_core_info *ci)
  228 {
  229         struct bhndb_pci_core   *entry;
  230         struct bhndb_pci_quirk  *qtable;
  231         uint32_t                 quirks;
  232 
  233         quirks = 0;
  234 
  235         /* No core entry? */
  236         if ((entry = bhndb_pci_find_core(ci)) == NULL)
  237                 return (quirks);
  238 
  239         /* No quirks? */
  240         if ((qtable = entry->quirks) == NULL)
  241                 return (quirks);
  242 
  243         for (size_t i = 0; !BHNDB_PCI_IS_QUIRK_END(&qtable[i]); i++) {
  244                 struct bhndb_pci_quirk *q = &qtable[i];
  245 
  246                 if (!bhnd_chip_matches(cid, &q->chip_desc))
  247                         continue;
  248 
  249                 if (!bhnd_core_matches(ci, &q->core_desc))
  250                         continue;
  251 
  252                 quirks |= q->quirks;
  253         }
  254 
  255         return (quirks);
  256 }
  257 
  258 /** 
  259  * Default bhndb_pci implementation of device_probe().
  260  * 
  261  * Verifies that the parent is a PCI/PCIe device.
  262  */
  263 static int
  264 bhndb_pci_probe(device_t dev)
  265 {
  266         struct bhndb_pci_probe  *probe;
  267         struct bhndb_pci_core   *entry;
  268         bhnd_devclass_t          hostb_devclass;
  269         device_t                 parent, parent_bus;
  270         devclass_t               pci, bus_devclass;
  271         int                      error;
  272 
  273         probe = NULL;
  274 
  275         /* Our parent must be a PCI/PCIe device. */
  276         pci = devclass_find("pci");
  277         parent = device_get_parent(dev);
  278         parent_bus = device_get_parent(parent);
  279         if (parent_bus == NULL)
  280                 return (ENXIO);
  281 
  282         /* The bus device class may inherit from 'pci' */
  283         for (bus_devclass = device_get_devclass(parent_bus);
  284             bus_devclass != NULL;
  285             bus_devclass = devclass_get_parent(bus_devclass))
  286         {
  287                 if (bus_devclass == pci)
  288                         break;
  289         }
  290 
  291         if (bus_devclass != pci)
  292                 return (ENXIO);
  293 
  294         /* Enable clocks */
  295         if ((error = bhndb_enable_pci_clocks(dev)))
  296                 return (error);
  297 
  298         /* Identify the chip and enumerate the bridged cores */
  299         hostb_devclass = bhndb_expected_pci_devclass(dev);
  300         if ((error = bhndb_pci_probe_alloc(&probe, dev, hostb_devclass)))
  301                 goto cleanup;
  302 
  303         /* Look for a matching core table entry */
  304         if ((entry = bhndb_pci_find_core(&probe->hostb_core)) == NULL) {
  305                 error = ENXIO;
  306                 goto cleanup;
  307         }
  308 
  309         device_set_desc(dev, "PCI-BHND bridge");
  310 
  311         /* fall-through */
  312         error = BUS_PROBE_DEFAULT;
  313 
  314 cleanup:
  315         if (probe != NULL)
  316                 bhndb_pci_probe_free(probe);
  317 
  318         bhndb_disable_pci_clocks(dev);
  319 
  320         return (error);
  321 }
  322 
  323 /**
  324  * Attempt to allocate MSI interrupts, returning the count in @p msi_count
  325  * on success.
  326  */
  327 static int
  328 bhndb_pci_alloc_msi(struct bhndb_pci_softc *sc, int *msi_count)
  329 {
  330         int error, count;
  331 
  332         /* Is MSI available? */
  333         if (pci_msi_count(sc->parent) < BHNDB_PCI_MSI_COUNT)
  334                 return (ENXIO);
  335 
  336         /* Allocate expected message count */
  337         count = BHNDB_PCI_MSI_COUNT;
  338         if ((error = pci_alloc_msi(sc->parent, &count))) {
  339                 device_printf(sc->dev, "failed to allocate MSI interrupts: "
  340                     "%d\n", error);
  341 
  342                 return (error);
  343         }
  344 
  345         if (count < BHNDB_PCI_MSI_COUNT) {
  346                 pci_release_msi(sc->parent);
  347                 return (ENXIO);
  348         }
  349 
  350         *msi_count = count;
  351         return (0);
  352 }
  353 
  354 static int
  355 bhndb_pci_attach(device_t dev)
  356 {
  357         struct bhndb_pci_softc  *sc;
  358         struct bhnd_chipid       cid;
  359         struct bhnd_core_info   *cores, hostb_core;
  360         bhnd_erom_class_t       *erom_class;
  361         struct bhndb_pci_probe  *probe;
  362         u_int                    ncores;
  363         int                      irq_rid;
  364         int                      error;
  365 
  366         sc = device_get_softc(dev);
  367         sc->dev = dev;
  368         sc->parent = device_get_parent(dev);
  369         sc->pci_devclass = bhndb_expected_pci_devclass(dev);
  370         sc->pci_quirks = 0;
  371         sc->set_regwin = NULL;
  372 
  373         BHNDB_PCI_LOCK_INIT(sc);
  374 
  375         probe = NULL;
  376         cores = NULL;
  377 
  378         /* Enable PCI bus mastering */
  379         pci_enable_busmaster(sc->parent);
  380 
  381         /* Enable clocks (if required by this hardware) */
  382         if ((error = bhndb_enable_pci_clocks(sc->dev)))
  383                 goto cleanup;
  384 
  385         /* Identify the chip and enumerate the bridged cores */
  386         error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass);
  387         if (error)
  388                 goto cleanup;
  389 
  390         sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid,
  391             &probe->hostb_core);
  392 
  393         /* Select the appropriate register window handler */
  394         if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) {
  395                 sc->set_regwin = bhndb_pci_compat_setregwin;
  396         } else {
  397                 sc->set_regwin = bhndb_pci_fast_setregwin;
  398         }
  399 
  400         /*
  401          * Fix up our PCI base address in the SPROM shadow, if necessary.
  402          * 
  403          * This must be done prior to accessing any static register windows
  404          * that map the PCI core.
  405          */
  406         if ((error = bhndb_pci_srsh_pi_war(sc, probe)))
  407                 goto cleanup;
  408 
  409         /* Set up PCI interrupt handling */
  410         if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) {
  411                 /* MSI uses resource IDs starting at 1 */
  412                 irq_rid = 1;
  413 
  414                 device_printf(dev, "Using MSI interrupts on %s\n",
  415                     device_get_nameunit(sc->parent));
  416         } else {
  417                 sc->msi_count = 0;
  418                 irq_rid = 0;
  419 
  420                 device_printf(dev, "Using INTx interrupts on %s\n",
  421                     device_get_nameunit(sc->parent));
  422         }
  423 
  424         sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1,
  425             RF_SHAREABLE | RF_ACTIVE);
  426         if (sc->isrc == NULL) {
  427                 device_printf(sc->dev, "failed to allocate interrupt "
  428                     "resource\n");
  429                 error = ENXIO;
  430                 goto cleanup;
  431         }
  432 
  433         /*
  434          * Copy out the probe results and then free our probe state, releasing
  435          * its exclusive ownership of host bridge resources.
  436          * 
  437          * This must be done prior to full configuration of the bridge via
  438          * bhndb_attach().
  439          */
  440         cid = probe->cid;
  441         erom_class = probe->erom_class;
  442         hostb_core = probe->hostb_core;
  443 
  444         error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores);
  445         if (error) {
  446                 cores = NULL;
  447                 goto cleanup;
  448         }
  449 
  450         bhndb_pci_probe_free(probe);
  451         probe = NULL;
  452 
  453         /* Perform bridge attach */
  454         error = bhndb_attach(dev, &cid, cores, ncores, &hostb_core, erom_class);
  455         if (error)
  456                 goto cleanup;
  457 
  458         /* Add any additional child devices */
  459         if ((error = bhndb_pci_add_children(sc)))
  460                 goto cleanup;
  461 
  462         /* Probe and attach our children */
  463         if ((error = bus_generic_attach(dev)))
  464                 goto cleanup;
  465 
  466         bhndb_pci_probe_free_core_table(cores);
  467 
  468         return (0);
  469 
  470 cleanup:
  471         device_delete_children(dev);
  472 
  473         if (sc->isrc != NULL)
  474                 bhndb_free_intr_isrc(sc->isrc);
  475 
  476         if (sc->msi_count > 0)
  477                 pci_release_msi(sc->parent);
  478 
  479         if (cores != NULL)
  480                 bhndb_pci_probe_free_core_table(cores);
  481 
  482         if (probe != NULL)
  483                 bhndb_pci_probe_free(probe);
  484 
  485         bhndb_disable_pci_clocks(sc->dev);
  486 
  487         pci_disable_busmaster(sc->parent);
  488 
  489         BHNDB_PCI_LOCK_DESTROY(sc);
  490 
  491         return (error);
  492 }
  493 
  494 static int
  495 bhndb_pci_detach(device_t dev)
  496 {
  497         struct bhndb_pci_softc  *sc;
  498         int                      error;
  499 
  500         sc = device_get_softc(dev);
  501 
  502         /* Attempt to detach our children */
  503         if ((error = bus_generic_detach(dev)))
  504                 return (error);
  505 
  506         /* Perform generic bridge detach */
  507         if ((error = bhndb_generic_detach(dev)))
  508                 return (error);
  509 
  510         /* Disable clocks (if required by this hardware) */
  511         if ((error = bhndb_disable_pci_clocks(sc->dev)))
  512                 return (error);
  513 
  514         /* Free our interrupt resources */
  515         bhndb_free_intr_isrc(sc->isrc);
  516 
  517         /* Release MSI interrupts */
  518         if (sc->msi_count > 0)
  519                 pci_release_msi(sc->parent);
  520 
  521         /* Disable PCI bus mastering */
  522         pci_disable_busmaster(sc->parent);
  523 
  524         BHNDB_PCI_LOCK_DESTROY(sc);
  525 
  526         return (0);
  527 }
  528 
  529 static int
  530 bhndb_pci_add_children(struct bhndb_pci_softc *sc)
  531 {
  532         bus_size_t               nv_sz;
  533         int                      error;
  534 
  535         /**
  536          * If SPROM is mapped directly into BAR0, add child NVRAM
  537          * device.
  538          */
  539         nv_sz = bhndb_pci_sprom_size(sc);
  540         if (nv_sz > 0) {
  541                 struct bhndb_devinfo    *dinfo;
  542                 device_t                 child;
  543 
  544                 if (bootverbose) {
  545                         device_printf(sc->dev, "found SPROM (%ju bytes)\n",
  546                             (uintmax_t)nv_sz);
  547                 }
  548 
  549                 /* Add sprom device, ordered early enough to be available
  550                  * before the bridged bhnd(4) bus is attached. */
  551                 child = BUS_ADD_CHILD(sc->dev,
  552                     BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY, "bhnd_nvram", -1);
  553                 if (child == NULL) {
  554                         device_printf(sc->dev, "failed to add sprom device\n");
  555                         return (ENXIO);
  556                 }
  557 
  558                 /* Initialize device address space and resource covering the
  559                  * BAR0 SPROM shadow. */
  560                 dinfo = device_get_ivars(child);
  561                 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
  562 
  563                 error = bus_set_resource(child, SYS_RES_MEMORY, 0,
  564                     bhndb_pci_sprom_addr(sc), nv_sz);
  565                 if (error) {
  566                         device_printf(sc->dev,
  567                             "failed to register sprom resources\n");
  568                         return (error);
  569                 }
  570         }
  571 
  572         return (0);
  573 }
  574 
  575 static const struct bhndb_regwin *
  576 bhndb_pci_sprom_regwin(struct bhndb_pci_softc *sc)
  577 {
  578         struct bhndb_resources          *bres;
  579         const struct bhndb_hwcfg        *cfg;
  580         const struct bhndb_regwin       *sprom_win;
  581 
  582         bres = sc->bhndb.bus_res;
  583         cfg = bres->cfg;
  584 
  585         sprom_win = bhndb_regwin_find_type(cfg->register_windows,
  586             BHNDB_REGWIN_T_SPROM, BHNDB_PCI_V0_BAR0_SPROM_SIZE);
  587 
  588         return (sprom_win);
  589 }
  590 
  591 static bus_addr_t
  592 bhndb_pci_sprom_addr(struct bhndb_pci_softc *sc)
  593 {
  594         const struct bhndb_regwin       *sprom_win;
  595         struct resource                 *r;
  596 
  597         /* Fetch the SPROM register window */
  598         sprom_win = bhndb_pci_sprom_regwin(sc);
  599         KASSERT(sprom_win != NULL, ("requested sprom address on PCI_V2+"));
  600 
  601         /* Fetch the associated resource */
  602         r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, sprom_win);
  603         KASSERT(r != NULL, ("missing resource for sprom window\n"));
  604 
  605         return (rman_get_start(r) + sprom_win->win_offset);
  606 }
  607 
  608 static bus_size_t
  609 bhndb_pci_sprom_size(struct bhndb_pci_softc *sc)
  610 {
  611         const struct bhndb_regwin       *sprom_win;
  612         uint32_t                         sctl;
  613         bus_size_t                       sprom_sz;
  614 
  615         sprom_win = bhndb_pci_sprom_regwin(sc);
  616 
  617         /* PCI_V2 and later devices map SPROM/OTP via ChipCommon */
  618         if (sprom_win == NULL)
  619                 return (0);
  620 
  621         /* Determine SPROM size */
  622         sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4);
  623         if (sctl & BHNDB_PCI_SPROM_BLANK)
  624                 return (0);
  625 
  626         switch (sctl & BHNDB_PCI_SPROM_SZ_MASK) {
  627         case BHNDB_PCI_SPROM_SZ_1KB:
  628                 sprom_sz = (1 * 1024);
  629                 break;
  630 
  631         case BHNDB_PCI_SPROM_SZ_4KB:
  632                 sprom_sz = (4 * 1024);
  633                 break;
  634 
  635         case BHNDB_PCI_SPROM_SZ_16KB:
  636                 sprom_sz = (16 * 1024);
  637                 break;
  638 
  639         case BHNDB_PCI_SPROM_SZ_RESERVED:
  640         default:
  641                 device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl);
  642                 return (0);
  643         }
  644 
  645         /* If the device has a larger SPROM than can be addressed via our SPROM
  646          * register window, the SPROM image data will still be located within
  647          * the window's addressable range */
  648         sprom_sz = MIN(sprom_sz, sprom_win->win_size);
  649 
  650         return (sprom_sz);
  651 }
  652 
  653 /**
  654  * Return the host resource providing a static mapping of the PCI core's
  655  * registers.
  656  * 
  657  * @param       sc              bhndb PCI driver state.
  658  * @param       offset          The required readable offset within the PCI core
  659  *                              register block.
  660  * @param       size            The required readable size at @p offset.
  661  * @param[out]  res             On success, the host resource containing our PCI
  662  *                              core's register window.
  663  * @param[out]  res_offset      On success, the @p offset relative to @p res.
  664  *
  665  * @retval 0            success
  666  * @retval ENXIO        if a valid static register window mapping the PCI core
  667  *                      registers is not available.
  668  */
  669 static int
  670 bhndb_pci_get_core_regs(struct bhndb_pci_softc *sc, bus_size_t offset,
  671     bus_size_t size, struct resource **res, bus_size_t *res_offset)
  672 {
  673         const struct bhndb_regwin       *win;
  674         struct resource                 *r;
  675 
  676         /* Locate the static register window mapping the requested offset */
  677         win = bhndb_regwin_find_core(sc->bhndb.bus_res->cfg->register_windows,
  678             sc->pci_devclass, 0, BHND_PORT_DEVICE, 0, 0, offset, size);
  679         if (win == NULL) {
  680                 device_printf(sc->dev, "missing PCI core register window\n");
  681                 return (ENXIO);
  682         }
  683 
  684         /* Fetch the resource containing the register window */
  685         r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, win);
  686         if (r == NULL) {
  687                 device_printf(sc->dev, "missing PCI core register resource\n");
  688                 return (ENXIO);
  689         }
  690 
  691         KASSERT(offset >= win->d.core.offset, ("offset %#jx outside of "
  692             "register window", (uintmax_t)offset));
  693 
  694         *res = r;
  695         *res_offset = win->win_offset + (offset - win->d.core.offset);
  696 
  697         return (0);
  698 }
  699 
  700 /**
  701  * Write a 1, 2, or 4 byte data item to the PCI core's registers at @p offset.
  702  * 
  703  * @param sc            bhndb PCI driver state.
  704  * @param offset        register write offset.
  705  * @param value         value to be written.
  706  * @param width         item width (1, 2, or 4 bytes).
  707  */
  708 static void
  709 bhndb_pci_write_core(struct bhndb_pci_softc *sc, bus_size_t offset,
  710     uint32_t value, u_int width)
  711 {
  712         struct resource *r;
  713         bus_size_t       r_offset;
  714         int              error;
  715 
  716         error = bhndb_pci_get_core_regs(sc, offset, width, &r, &r_offset);
  717         if (error) {
  718                 panic("no PCI register window mapping %#jx+%#x: %d",
  719                     (uintmax_t)offset, width, error);
  720         }
  721 
  722         switch (width) {
  723         case 1:
  724                 bus_write_1(r, r_offset, value);
  725                 break;
  726         case 2:
  727                 bus_write_2(r, r_offset, value);
  728                 break;
  729         case 4:
  730                 bus_write_4(r, r_offset, value);
  731                 break;
  732         default:
  733                 panic("invalid width: %u", width);
  734         }
  735 }
  736 
  737 /**
  738  * Read a 1, 2, or 4 byte data item from the PCI core's registers
  739  * at @p offset.
  740  * 
  741  * @param sc            bhndb PCI driver state.
  742  * @param offset        register read offset.
  743  * @param width         item width (1, 2, or 4 bytes).
  744  */
  745 static uint32_t
  746 bhndb_pci_read_core(struct bhndb_pci_softc *sc, bus_size_t offset, u_int width)
  747 {
  748         struct resource *r;
  749         bus_size_t       r_offset;
  750         int              error;
  751 
  752         error = bhndb_pci_get_core_regs(sc, offset, width, &r, &r_offset);
  753         if (error) {
  754                 panic("no PCI register window mapping %#jx+%#x: %d",
  755                     (uintmax_t)offset, width, error);
  756         }
  757 
  758         switch (width) {
  759         case 1:
  760                 return (bus_read_1(r, r_offset));
  761         case 2:
  762                 return (bus_read_2(r, r_offset));
  763         case 4:
  764                 return (bus_read_4(r, r_offset));
  765         default:
  766                 panic("invalid width: %u", width);
  767         }
  768 }
  769 
  770 /**
  771  * Fix-up power on defaults for SPROM-less devices.
  772  *
  773  * On SPROM-less devices, the PCI(e) cores will be initialized with their their
  774  * Power-on-Reset defaults; this can leave the BHND_PCI_SRSH_PI value pointing
  775  * to the wrong backplane address. This value is used by the PCI core when
  776  * performing address translation between static register windows in BAR0 that
  777  * map the PCI core's register block, and backplane address space.
  778  *
  779  * When translating accesses via these BAR0 regions, the PCI bridge determines
  780  * the base address of the PCI core by concatenating:
  781  *
  782  *      [bits]  [source]
  783  *      31:16   bits [31:16] of the enumeration space address (e.g. 0x18000000)
  784  *      15:12   value of BHND_PCI_SRSH_PI from the PCI core's SPROM shadow
  785  *      11:0    bits [11:0] of the PCI bus address
  786  *
  787  * For example, on a PCI_V0 device, the following PCI core register offsets are
  788  * mapped into BAR0:
  789  *
  790  *      [BAR0 offset]           [description]           [PCI core offset]
  791  *      0x1000-0x17FF           sprom shadow            0x800-0xFFF
  792  *      0x1800-0x1DFF           device registers        0x000-0x5FF
  793  *      0x1E00+0x1FFF           siba config registers   0xE00-0xFFF
  794  *
  795  * This function checks -- and if necessary, corrects -- the BHND_PCI_SRSH_PI
  796  * value in the SPROM shadow. 
  797  *
  798  * This workaround must applied prior to accessing any static register windows
  799  * that map the PCI core.
  800  * 
  801  * Applies to all PCI and PCIe-G1 core revisions.
  802  */
  803 static int
  804 bhndb_pci_srsh_pi_war(struct bhndb_pci_softc *sc,
  805     struct bhndb_pci_probe *probe)
  806 {
  807         struct bhnd_core_match  md;
  808         bhnd_addr_t             pci_addr;
  809         bhnd_size_t             pci_size;
  810         bus_size_t              srsh_offset;
  811         uint16_t                srsh_val, pci_val;
  812         uint16_t                val;
  813         int                     error;
  814 
  815         if ((sc->pci_quirks & BHNDB_PCI_QUIRK_SRSH_WAR) == 0)
  816                 return (0);
  817 
  818         /* Use an equality match descriptor to look up our PCI core's base
  819          * address in the EROM */
  820         md = bhnd_core_get_match_desc(&probe->hostb_core);
  821         error = bhnd_erom_lookup_core_addr(probe->erom, &md, BHND_PORT_DEVICE,
  822             0, 0, NULL, &pci_addr, &pci_size);
  823         if (error) {
  824                 device_printf(sc->dev, "no base address found for the PCI host "
  825                     "bridge core: %d\n", error);
  826                 return (error);
  827         }
  828 
  829         /* Fetch the SPROM SRSH_PI value */
  830         srsh_offset = BHND_PCI_SPROM_SHADOW + BHND_PCI_SRSH_PI_OFFSET;
  831         val = bhndb_pci_probe_read(probe, pci_addr, srsh_offset, sizeof(val));
  832         srsh_val = (val & BHND_PCI_SRSH_PI_MASK) >> BHND_PCI_SRSH_PI_SHIFT;
  833 
  834         /* If it doesn't match PCI core's base address, update the SPROM
  835          * shadow */
  836         pci_val = (pci_addr & BHND_PCI_SRSH_PI_ADDR_MASK) >>
  837             BHND_PCI_SRSH_PI_ADDR_SHIFT;
  838         if (srsh_val != pci_val) {
  839                 val &= ~BHND_PCI_SRSH_PI_MASK;
  840                 val |= (pci_val << BHND_PCI_SRSH_PI_SHIFT);
  841                 bhndb_pci_probe_write(probe, pci_addr, srsh_offset, val,
  842                     sizeof(val));
  843         }
  844 
  845         return (0);
  846 }
  847 
  848 static int
  849 bhndb_pci_resume(device_t dev)
  850 {
  851         struct bhndb_pci_softc  *sc;
  852         int                      error;
  853 
  854         sc = device_get_softc(dev);
  855 
  856         /* Enable clocks (if supported by this hardware) */
  857         if ((error = bhndb_enable_pci_clocks(sc->dev)))
  858                 return (error);
  859 
  860         /* Perform resume */
  861         return (bhndb_generic_resume(dev));
  862 }
  863 
  864 static int
  865 bhndb_pci_suspend(device_t dev)
  866 {
  867         struct bhndb_pci_softc  *sc;
  868         int                      error;
  869 
  870         sc = device_get_softc(dev);
  871 
  872         /* Disable clocks (if supported by this hardware) */
  873         if ((error = bhndb_disable_pci_clocks(sc->dev)))
  874                 return (error);
  875 
  876         /* Perform suspend */
  877         return (bhndb_generic_suspend(dev));
  878 }
  879 
  880 static int
  881 bhndb_pci_set_window_addr(device_t dev, const struct bhndb_regwin *rw,
  882     bhnd_addr_t addr)
  883 {
  884         struct bhndb_pci_softc *sc = device_get_softc(dev);
  885         return (sc->set_regwin(sc->dev, sc->parent, rw, addr));
  886 }
  887 
  888 /**
  889  * A siba(4) and bcma(4)-compatible bhndb_set_window_addr implementation.
  890  * 
  891  * On siba(4) devices, it's possible that writing a PCI window register may
  892  * not succeed; it's necessary to immediately read the configuration register
  893  * and retry if not set to the desired value.
  894  * 
  895  * This is not necessary on bcma(4) devices, but other than the overhead of
  896  * validating the register, there's no harm in performing the verification.
  897  */
  898 static int
  899 bhndb_pci_compat_setregwin(device_t dev, device_t pci_dev,
  900     const struct bhndb_regwin *rw, bhnd_addr_t addr)
  901 {
  902         int             error;
  903         int             reg;
  904 
  905         if (rw->win_type != BHNDB_REGWIN_T_DYN)
  906                 return (ENODEV);
  907 
  908         reg = rw->d.dyn.cfg_offset;
  909         for (u_int i = 0; i < BHNDB_PCI_BARCTRL_WRITE_RETRY; i++) {
  910                 if ((error = bhndb_pci_fast_setregwin(dev, pci_dev, rw, addr)))
  911                         return (error);
  912 
  913                 if (pci_read_config(pci_dev, reg, 4) == addr)
  914                         return (0);
  915 
  916                 DELAY(10);
  917         }
  918 
  919         /* Unable to set window */
  920         return (ENODEV);
  921 }
  922 
  923 /**
  924  * A bcma(4)-only bhndb_set_window_addr implementation.
  925  */
  926 static int
  927 bhndb_pci_fast_setregwin(device_t dev, device_t pci_dev,
  928     const struct bhndb_regwin *rw, bhnd_addr_t addr)
  929 {
  930         /* The PCI bridge core only supports 32-bit addressing, regardless
  931          * of the bus' support for 64-bit addressing */
  932         if (addr > UINT32_MAX)
  933                 return (ERANGE);
  934 
  935         switch (rw->win_type) {
  936         case BHNDB_REGWIN_T_DYN:
  937                 /* Addresses must be page aligned */
  938                 if (addr % rw->win_size != 0)
  939                         return (EINVAL);
  940 
  941                 pci_write_config(pci_dev, rw->d.dyn.cfg_offset, addr, 4);
  942                 break;
  943         default:
  944                 return (ENODEV);
  945         }
  946 
  947         return (0);
  948 }
  949 
  950 static int
  951 bhndb_pci_populate_board_info(device_t dev, device_t child,
  952     struct bhnd_board_info *info)
  953 {
  954         struct bhndb_pci_softc  *sc;
  955 
  956         sc = device_get_softc(dev);
  957 
  958         /* 
  959          * On a subset of Apple BCM4360 modules, always prefer the
  960          * PCI subdevice to the SPROM-supplied boardtype.
  961          * 
  962          * TODO:
  963          * 
  964          * Broadcom's own drivers implement this override, and then later use
  965          * the remapped BCM4360 board type to determine the required
  966          * board-specific workarounds.
  967          * 
  968          * Without access to this hardware, it's unclear why this mapping
  969          * is done, and we must do the same. If we can survey the hardware
  970          * in question, it may be possible to replace this behavior with
  971          * explicit references to the SPROM-supplied boardtype(s) in our
  972          * quirk definitions.
  973          */
  974         if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) {
  975                 switch (info->board_type) {
  976                 case BHND_BOARD_BCM94360X29C:
  977                 case BHND_BOARD_BCM94360X29CP2:
  978                 case BHND_BOARD_BCM94360X51:
  979                 case BHND_BOARD_BCM94360X51P2:
  980                         info->board_type = 0;   /* allow override below */
  981                         break;
  982                 default:
  983                         break;
  984                 }
  985         }
  986 
  987         /* If NVRAM did not supply vendor/type/devid info, provide the PCI
  988          * subvendor/subdevice/device values. */
  989         if (info->board_vendor == 0)
  990                 info->board_vendor = pci_get_subvendor(sc->parent);
  991 
  992         if (info->board_type == 0)
  993                 info->board_type = pci_get_subdevice(sc->parent);
  994 
  995         if (info->board_devid == 0)
  996                 info->board_devid = pci_get_device(sc->parent);
  997 
  998         return (0);
  999 }
 1000 
 1001 /**
 1002  * Examine the bridge device @p dev and return the expected host bridge
 1003  * device class.
 1004  *
 1005  * @param dev The bhndb bridge device
 1006  */
 1007 static bhnd_devclass_t
 1008 bhndb_expected_pci_devclass(device_t dev)
 1009 {
 1010         if (bhndb_is_pcie_attached(dev))
 1011                 return (BHND_DEVCLASS_PCIE);
 1012         else
 1013                 return (BHND_DEVCLASS_PCI);
 1014 }
 1015 
 1016 /**
 1017  * Return true if the bridge device @p dev is attached via PCIe,
 1018  * false otherwise.
 1019  *
 1020  * @param dev The bhndb bridge device
 1021  */
 1022 static bool
 1023 bhndb_is_pcie_attached(device_t dev)
 1024 {
 1025         int reg;
 1026 
 1027         if (pci_find_cap(device_get_parent(dev), PCIY_EXPRESS, &reg) == 0)
 1028                 return (true);
 1029 
 1030         return (false);
 1031 }
 1032 
 1033 /**
 1034  * Enable externally managed clocks, if required.
 1035  * 
 1036  * Some PCI chipsets (BCM4306, possibly others) chips do not support
 1037  * the idle low-power clock. Clocking must be bootstrapped at
 1038  * attach/resume by directly adjusting GPIO registers exposed in the
 1039  * PCI config space, and correspondingly, explicitly shutdown at
 1040  * detach/suspend.
 1041  *
 1042  * @note This function may be safely called prior to device attach, (e.g.
 1043  * from DEVICE_PROBE).
 1044  *
 1045  * @param dev The bhndb bridge device
 1046  */
 1047 static int
 1048 bhndb_enable_pci_clocks(device_t dev)
 1049 {
 1050         device_t                pci_dev;
 1051         uint32_t                gpio_in, gpio_out, gpio_en;
 1052         uint32_t                gpio_flags;
 1053         uint16_t                pci_status;
 1054 
 1055         pci_dev = device_get_parent(dev);
 1056 
 1057         /* Only supported and required on PCI devices */
 1058         if (bhndb_is_pcie_attached(dev))
 1059                 return (0);
 1060 
 1061         /* Read state of XTAL pin */
 1062         gpio_in = pci_read_config(pci_dev, BHNDB_PCI_GPIO_IN, 4);
 1063         if (gpio_in & BHNDB_PCI_GPIO_XTAL_ON)
 1064                 return (0); /* already enabled */
 1065 
 1066         /* Fetch current config */
 1067         gpio_out = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUT, 4);
 1068         gpio_en = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, 4);
 1069 
 1070         /* Set PLL_OFF/XTAL_ON pins to HIGH and enable both pins */
 1071         gpio_flags = (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
 1072         gpio_out |= gpio_flags;
 1073         gpio_en |= gpio_flags;
 1074 
 1075         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
 1076         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
 1077         DELAY(1000);
 1078 
 1079         /* Reset PLL_OFF */
 1080         gpio_out &= ~BHNDB_PCI_GPIO_PLL_OFF;
 1081         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
 1082         DELAY(5000);
 1083 
 1084         /* Clear any PCI 'sent target-abort' flag. */
 1085         pci_status = pci_read_config(pci_dev, PCIR_STATUS, 2);
 1086         pci_status &= ~PCIM_STATUS_STABORT;
 1087         pci_write_config(pci_dev, PCIR_STATUS, pci_status, 2);
 1088 
 1089         return (0);
 1090 }
 1091 
 1092 /**
 1093  * Disable externally managed clocks, if required.
 1094  *
 1095  * This function may be safely called prior to device attach, (e.g.
 1096  * from DEVICE_PROBE).
 1097  *
 1098  * @param dev The bhndb bridge device
 1099  */
 1100 static int
 1101 bhndb_disable_pci_clocks(device_t dev)
 1102 {
 1103         device_t        pci_dev;
 1104         uint32_t        gpio_out, gpio_en;
 1105 
 1106         pci_dev = device_get_parent(dev);
 1107 
 1108         /* Only supported and required on PCI devices */
 1109         if (bhndb_is_pcie_attached(dev))
 1110                 return (0);
 1111 
 1112         /* Fetch current config */
 1113         gpio_out = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUT, 4);
 1114         gpio_en = pci_read_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, 4);
 1115 
 1116         /* Set PLL_OFF to HIGH, XTAL_ON to LOW. */
 1117         gpio_out &= ~BHNDB_PCI_GPIO_XTAL_ON;
 1118         gpio_out |= BHNDB_PCI_GPIO_PLL_OFF;
 1119         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUT, gpio_out, 4);
 1120 
 1121         /* Enable both output pins */
 1122         gpio_en |= (BHNDB_PCI_GPIO_PLL_OFF|BHNDB_PCI_GPIO_XTAL_ON);
 1123         pci_write_config(pci_dev, BHNDB_PCI_GPIO_OUTEN, gpio_en, 4);
 1124 
 1125         return (0);
 1126 }
 1127 
 1128 static bhnd_clksrc
 1129 bhndb_pci_pwrctl_get_clksrc(device_t dev, device_t child,
 1130         bhnd_clock clock)
 1131 {
 1132         struct bhndb_pci_softc  *sc;
 1133         uint32_t                 gpio_out;
 1134 
 1135         sc = device_get_softc(dev);
 1136 
 1137         /* Only supported on PCI devices */
 1138         if (bhndb_is_pcie_attached(sc->dev))
 1139                 return (BHND_CLKSRC_UNKNOWN);
 1140 
 1141         /* Only ILP is supported */
 1142         if (clock != BHND_CLOCK_ILP)
 1143                 return (BHND_CLKSRC_UNKNOWN);
 1144 
 1145         gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
 1146         if (gpio_out & BHNDB_PCI_GPIO_SCS)
 1147                 return (BHND_CLKSRC_PCI);
 1148         else
 1149                 return (BHND_CLKSRC_XTAL);
 1150 }
 1151 
 1152 static int
 1153 bhndb_pci_pwrctl_gate_clock(device_t dev, device_t child,
 1154         bhnd_clock clock)
 1155 {
 1156         struct bhndb_pci_softc *sc = device_get_softc(dev);
 1157 
 1158         /* Only supported on PCI devices */
 1159         if (bhndb_is_pcie_attached(sc->dev))
 1160                 return (ENODEV);
 1161 
 1162         /* Only HT is supported */
 1163         if (clock != BHND_CLOCK_HT)
 1164                 return (ENXIO);
 1165 
 1166         return (bhndb_disable_pci_clocks(sc->dev));
 1167 }
 1168 
 1169 static int
 1170 bhndb_pci_pwrctl_ungate_clock(device_t dev, device_t child,
 1171         bhnd_clock clock)
 1172 {
 1173         struct bhndb_pci_softc *sc = device_get_softc(dev);
 1174 
 1175         /* Only supported on PCI devices */
 1176         if (bhndb_is_pcie_attached(sc->dev))
 1177                 return (ENODEV);
 1178 
 1179         /* Only HT is supported */
 1180         if (clock != BHND_CLOCK_HT)
 1181                 return (ENXIO);
 1182 
 1183         return (bhndb_enable_pci_clocks(sc->dev));
 1184 }
 1185 
 1186 /**
 1187  * BHNDB_MAP_INTR_ISRC()
 1188  */
 1189 static int
 1190 bhndb_pci_map_intr_isrc(device_t dev, struct resource *irq,
 1191     struct bhndb_intr_isrc **isrc)
 1192 {
 1193         struct bhndb_pci_softc *sc = device_get_softc(dev);
 1194 
 1195         /* There's only one bridged interrupt to choose from */
 1196         *isrc = sc->isrc;
 1197         return (0);
 1198 }
 1199 
 1200 /* siba-specific implementation of BHNDB_ROUTE_INTERRUPTS() */
 1201 static int
 1202 bhndb_pci_route_siba_interrupts(struct bhndb_pci_softc *sc, device_t child)
 1203 {
 1204         uint32_t        sbintvec;
 1205         u_int           ivec;
 1206         int             error;
 1207 
 1208         KASSERT(sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC,
 1209             ("route_siba_interrupts not supported by this hardware"));
 1210 
 1211         /* Fetch the sbflag# for the child */
 1212         if ((error = bhnd_get_intr_ivec(child, 0, &ivec)))
 1213                 return (error);
 1214 
 1215         if (ivec > (sizeof(sbintvec)*8) - 1 /* aka '31' */) {
 1216                 /* This should never be an issue in practice */
 1217                 device_printf(sc->dev, "cannot route interrupts to high "
 1218                     "sbflag# %u\n", ivec);
 1219                 return (ENXIO);
 1220         }
 1221 
 1222         BHNDB_PCI_LOCK(sc);
 1223 
 1224         sbintvec = bhndb_pci_read_core(sc, SB0_REG_ABS(SIBA_CFG0_INTVEC), 4);
 1225         sbintvec |= (1 << ivec);
 1226         bhndb_pci_write_core(sc, SB0_REG_ABS(SIBA_CFG0_INTVEC), sbintvec, 4);
 1227 
 1228         BHNDB_PCI_UNLOCK(sc);
 1229 
 1230         return (0);
 1231 }
 1232 
 1233 /* BHNDB_ROUTE_INTERRUPTS() */
 1234 static int
 1235 bhndb_pci_route_interrupts(device_t dev, device_t child)
 1236 {
 1237         struct bhndb_pci_softc  *sc;
 1238         struct bhnd_core_info    core;
 1239         uint32_t                 core_bit;
 1240         uint32_t                 intmask;
 1241 
 1242         sc = device_get_softc(dev);
 1243 
 1244         if (sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC)
 1245                 return (bhndb_pci_route_siba_interrupts(sc, child));
 1246 
 1247         core = bhnd_get_core_info(child);
 1248         if (core.core_idx > BHNDB_PCI_SBIM_COREIDX_MAX) {
 1249                 /* This should never be an issue in practice */
 1250                 device_printf(dev, "cannot route interrupts to high core "
 1251                     "index %u\n", core.core_idx);
 1252                 return (ENXIO);
 1253         }
 1254 
 1255         BHNDB_PCI_LOCK(sc);
 1256 
 1257         core_bit = (1<<core.core_idx) << BHNDB_PCI_SBIM_SHIFT;
 1258         intmask = pci_read_config(sc->parent, BHNDB_PCI_INT_MASK, 4);
 1259         intmask |= core_bit;
 1260         pci_write_config(sc->parent, BHNDB_PCI_INT_MASK, intmask, 4);
 1261 
 1262         BHNDB_PCI_UNLOCK(sc);
 1263 
 1264         return (0);
 1265 }
 1266 
 1267 /**
 1268  * Using the generic PCI bridge hardware configuration, allocate, initialize
 1269  * and return a new bhndb_pci probe state instance.
 1270  * 
 1271  * On success, the caller assumes ownership of the returned probe instance, and
 1272  * is responsible for releasing this reference using bhndb_pci_probe_free().
 1273  * 
 1274  * @param[out]  probe           On success, the newly allocated probe instance.
 1275  * @param       dev             The bhndb_pci bridge device.
 1276  * @param       hostb_devclass  The expected device class of the bridge core.
 1277  *
 1278  * @retval 0            success
 1279  * @retval non-zero     if allocating the probe state fails, a regular
 1280  *                      unix error code will be returned.
 1281  * 
 1282  * @note This function requires exclusive ownership over allocating and 
 1283  * configuring host bridge resources, and should only be called prior to
 1284  * completion of device attach and full configuration of the bridge.
 1285  */
 1286 static int
 1287 bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe, device_t dev,
 1288     bhnd_devclass_t hostb_devclass)
 1289 {
 1290         struct bhndb_pci_probe          *p;
 1291         struct bhnd_erom_io             *eio;
 1292         const struct bhndb_hwcfg        *hwcfg;
 1293         const struct bhnd_chipid        *hint;
 1294         device_t                         parent_dev;
 1295         int                              error;
 1296 
 1297         parent_dev = device_get_parent(dev);
 1298         eio = NULL;
 1299 
 1300         p = malloc(sizeof(*p), M_BHND, M_ZERO|M_WAITOK);
 1301         p->dev = dev;
 1302         p->pci_dev = parent_dev;
 1303 
 1304         /* Our register window mapping state must be initialized at this point,
 1305          * as bhndb_pci_eio will begin making calls into
 1306          * bhndb_pci_probe_(read|write|get_mapping) */
 1307         p->m_win = NULL;
 1308         p->m_res = NULL;
 1309         p->m_valid = false;
 1310 
 1311         bhndb_pci_eio_init(&p->erom_io, p);
 1312         eio = &p->erom_io.eio;
 1313 
 1314         /* Fetch our chipid hint (if any) and generic hardware configuration */
 1315         hwcfg = BHNDB_BUS_GET_GENERIC_HWCFG(parent_dev, dev);
 1316         hint = BHNDB_BUS_GET_CHIPID(parent_dev, dev);
 1317 
 1318         /* Allocate our host resources */
 1319         error = bhndb_alloc_host_resources(&p->hr, dev, parent_dev, hwcfg);
 1320         if (error) {
 1321                 p->hr = NULL;
 1322                 goto failed;
 1323         }
 1324 
 1325         /* Map the first bus core from our bridged bhnd(4) bus */
 1326         error = bhnd_erom_io_map(eio, BHND_DEFAULT_CHIPC_ADDR,
 1327             BHND_DEFAULT_CORE_SIZE);
 1328         if (error)
 1329                 goto failed;
 1330 
 1331         /* Probe for a usable EROM class, and read the chip identifier */
 1332         p->erom_class = bhnd_erom_probe_driver_classes(
 1333             device_get_devclass(dev), eio, hint, &p->cid);
 1334         if (p->erom_class == NULL) {
 1335                 device_printf(dev, "device enumeration unsupported; no "
 1336                     "compatible driver found\n");
 1337 
 1338                 error = ENXIO;
 1339                 goto failed;
 1340         }
 1341 
 1342         /* Allocate EROM parser */
 1343         p->erom = bhnd_erom_alloc(p->erom_class, &p->cid, eio);
 1344         if (p->erom == NULL) {
 1345                 device_printf(dev, "failed to allocate device enumeration "
 1346                     "table parser\n");
 1347                 error = ENXIO;
 1348                 goto failed;
 1349         }
 1350 
 1351         /* The EROM I/O instance is now owned by our EROM parser */
 1352         eio = NULL;
 1353 
 1354         /* Read the full core table */
 1355         error = bhnd_erom_get_core_table(p->erom, &p->cores, &p->ncores);
 1356         if (error) {
 1357                 device_printf(p->dev, "error fetching core table: %d\n",
 1358                     error);
 1359 
 1360                 p->cores = NULL;
 1361                 goto failed;
 1362         }
 1363 
 1364         /* Identify the host bridge core */
 1365         error = bhndb_find_hostb_core(p->cores, p->ncores, hostb_devclass,
 1366             &p->hostb_core);
 1367         if (error) {
 1368                 device_printf(dev, "failed to identify the host bridge "
 1369                     "core: %d\n", error);
 1370 
 1371                 goto failed;
 1372         }
 1373 
 1374         *probe = p;
 1375         return (0);
 1376 
 1377 failed:
 1378         if (eio != NULL) {
 1379                 KASSERT(p->erom == NULL, ("I/O instance will be freed by "
 1380                     "its owning parser"));
 1381 
 1382                 bhnd_erom_io_fini(eio);
 1383         }
 1384 
 1385         if (p->erom != NULL) {
 1386                 if (p->cores != NULL)
 1387                         bhnd_erom_free_core_table(p->erom, p->cores);
 1388 
 1389                 bhnd_erom_free(p->erom);
 1390         } else {
 1391                 KASSERT(p->cores == NULL, ("cannot free erom-owned core table "
 1392                     "without erom reference"));
 1393         }
 1394 
 1395         if (p->hr != NULL)
 1396                 bhndb_release_host_resources(p->hr);
 1397 
 1398         free(p, M_BHND);
 1399 
 1400         return (error);
 1401 }
 1402 
 1403 /**
 1404  * Free the given @p probe instance and any associated host bridge resources.
 1405  */
 1406 static void
 1407 bhndb_pci_probe_free(struct bhndb_pci_probe *probe)
 1408 {
 1409         bhnd_erom_free_core_table(probe->erom, probe->cores);
 1410         bhnd_erom_free(probe->erom);
 1411         bhndb_release_host_resources(probe->hr);
 1412         free(probe, M_BHND);
 1413 }
 1414 
 1415 /**
 1416  * Return a copy of probed core table from @p probe.
 1417  * 
 1418  * @param       probe           The probe instance.
 1419  * @param[out]  cores           On success, a copy of the probed core table. The
 1420  *                              caller is responsible for freeing this table
 1421  *                              bhndb_pci_probe_free_core_table().
 1422  * @param[out]  ncores          On success, the number of cores found in
 1423  *                              @p cores.
 1424  * 
 1425  * @retval 0            success
 1426  * @retval non-zero     if enumerating the bridged bhnd(4) bus fails, a regular
 1427  *                      unix error code will be returned.
 1428  */
 1429 static int
 1430 bhndb_pci_probe_copy_core_table(struct bhndb_pci_probe *probe,
 1431     struct bhnd_core_info **cores, u_int *ncores)
 1432 {
 1433         size_t len = sizeof(**cores) * probe->ncores;
 1434 
 1435         *cores = malloc(len, M_BHND, M_WAITOK);
 1436         memcpy(*cores, probe->cores, len);
 1437 
 1438         *ncores = probe->ncores;
 1439 
 1440         return (0);
 1441 }
 1442 
 1443 /**
 1444  * Free a core table previously returned by bhndb_pci_probe_copy_core_table().
 1445  * 
 1446  * @param cores The core table to be freed.
 1447  */
 1448 static void
 1449 bhndb_pci_probe_free_core_table(struct bhnd_core_info *cores)
 1450 {
 1451         free(cores, M_BHND);
 1452 }
 1453 
 1454 /**
 1455  * Return true if @p addr and @p size are mapped by the dynamic register window
 1456  * backing @p probe. 
 1457  */
 1458 static bool
 1459 bhndb_pci_probe_has_mapping(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
 1460     bhnd_size_t size)
 1461 {
 1462         if (!probe->m_valid)
 1463                 return (false);
 1464 
 1465         KASSERT(probe->m_win != NULL, ("missing register window"));
 1466         KASSERT(probe->m_res != NULL, ("missing regwin resource"));
 1467         KASSERT(probe->m_win->win_type == BHNDB_REGWIN_T_DYN,
 1468             ("unexpected window type %d", probe->m_win->win_type));
 1469 
 1470         if (addr < probe->m_target)
 1471                 return (false);
 1472 
 1473         if (addr >= probe->m_target + probe->m_win->win_size)
 1474                 return (false);
 1475 
 1476         if ((probe->m_target + probe->m_win->win_size) - addr < size)
 1477                 return (false);
 1478 
 1479         return (true);
 1480 }
 1481 
 1482 /**
 1483  * Attempt to adjust the dynamic register window backing @p probe to permit
 1484  * accessing @p size bytes at @p addr.
 1485  * 
 1486  * @param       probe           The bhndb_pci probe state to be modified.
 1487  * @param       addr            The address at which @p size bytes will mapped.
 1488  * @param       size            The number of bytes to be mapped.
 1489  * @param[out]  res             On success, will be set to the host resource
 1490  *                              mapping @p size bytes at @p addr.
 1491  * @param[out]  res_offset      On success, will be set to the offset of @addr
 1492  *                              within @p res.
 1493  * 
 1494  * @retval 0            success
 1495  * @retval non-zero     if an error occurs adjusting the backing dynamic
 1496  *                      register window.
 1497  */
 1498 static int
 1499 bhndb_pci_probe_map(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
 1500     bhnd_size_t offset, bhnd_size_t size, struct resource **res,
 1501     bus_size_t *res_offset)
 1502 {
 1503         const struct bhndb_regwin       *regwin, *regwin_table;
 1504         struct resource                 *regwin_res;
 1505         bhnd_addr_t                      target;
 1506         int                              error;
 1507 
 1508         /* Determine the absolute address */
 1509         if (BHND_SIZE_MAX - offset < addr) {
 1510                 device_printf(probe->dev, "invalid offset %#jx+%#jx\n", addr,
 1511                     offset);
 1512                 return (ENXIO);
 1513         }
 1514 
 1515         addr += offset;
 1516 
 1517         /* Can we use the existing mapping? */
 1518         if (bhndb_pci_probe_has_mapping(probe, addr, size)) {
 1519                 *res = probe->m_res;
 1520                 *res_offset = (addr - probe->m_target) +
 1521                     probe->m_win->win_offset;
 1522 
 1523                 return (0);
 1524         }
 1525 
 1526         /* Locate a useable dynamic register window */
 1527         regwin_table = probe->hr->cfg->register_windows;
 1528         regwin = bhndb_regwin_find_type(regwin_table,
 1529             BHNDB_REGWIN_T_DYN, size);
 1530         if (regwin == NULL) {
 1531                 device_printf(probe->dev, "unable to map %#jx+%#jx; no "
 1532                     "usable dynamic register window found\n", addr,
 1533                     size);
 1534                 return (ENXIO);
 1535         }
 1536 
 1537         /* Locate the host resource mapping our register window */
 1538         regwin_res = bhndb_host_resource_for_regwin(probe->hr, regwin);
 1539         if (regwin_res == NULL) {
 1540                 device_printf(probe->dev, "unable to map %#jx+%#jx; no "
 1541                     "usable register resource found\n", addr, size);
 1542                 return (ENXIO);
 1543         }
 1544 
 1545         /* Page-align the target address */
 1546         target = addr - (addr % regwin->win_size);
 1547 
 1548         /* Configure the register window */
 1549         error = bhndb_pci_compat_setregwin(probe->dev, probe->pci_dev,
 1550             regwin, target);
 1551         if (error) {
 1552                 device_printf(probe->dev, "failed to configure dynamic "
 1553                     "register window: %d\n", error);
 1554                 return (error);
 1555         }
 1556 
 1557         /* Update our mapping state */
 1558         probe->m_win = regwin;
 1559         probe->m_res = regwin_res;
 1560         probe->m_addr = addr;
 1561         probe->m_size = size;
 1562         probe->m_target = target;
 1563         probe->m_valid = true;
 1564 
 1565         *res = regwin_res;
 1566         *res_offset = (addr - target) + regwin->win_offset;
 1567 
 1568         return (0);
 1569 }
 1570 
 1571 /**
 1572  * Write a data item to the bridged address space at the given @p offset from
 1573  * @p addr.
 1574  *
 1575  * A dynamic register window will be used to map @p addr.
 1576  * 
 1577  * @param probe         The bhndb_pci probe state to be used to perform the
 1578  *                      write.
 1579  * @param addr          The base address.
 1580  * @param offset        The offset from @p addr at which @p value will be
 1581  *                      written.
 1582  * @param value         The data item to be written.
 1583  * @param width         The data item width (1, 2, or 4 bytes).
 1584  */
 1585 static void
 1586 bhndb_pci_probe_write(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
 1587     bhnd_size_t offset, uint32_t value, u_int width)
 1588 {
 1589         struct resource *r;
 1590         bus_size_t       res_offset;
 1591         int              error;
 1592 
 1593         /* Map the target address */
 1594         error = bhndb_pci_probe_map(probe, addr, offset, width, &r,
 1595             &res_offset);
 1596         if (error) {
 1597                 device_printf(probe->dev, "error mapping %#jx+%#jx for "
 1598                     "writing: %d\n", addr, offset, error);
 1599                 return;
 1600         }
 1601 
 1602         /* Perform write */
 1603         switch (width) {
 1604         case 1:
 1605                 return (bus_write_1(r, res_offset, value));
 1606         case 2:
 1607                 return (bus_write_2(r, res_offset, value));
 1608         case 4:
 1609                 return (bus_write_4(r, res_offset, value));
 1610         default:
 1611                 panic("unsupported width: %u", width);
 1612         }
 1613 }
 1614 
 1615 /**
 1616  * Read a data item from the bridged address space at the given @p offset
 1617  * from @p addr.
 1618  * 
 1619  * A dynamic register window will be used to map @p addr.
 1620  * 
 1621  * @param probe         The bhndb_pci probe state to be used to perform the
 1622  *                      read.
 1623  * @param addr          The base address.
 1624  * @param offset        The offset from @p addr at which to read a data item of
 1625  *                      @p width bytes.
 1626  * @param width         Item width (1, 2, or 4 bytes).
 1627  */
 1628 static uint32_t
 1629 bhndb_pci_probe_read(struct bhndb_pci_probe *probe, bhnd_addr_t addr,
 1630     bhnd_size_t offset, u_int width)
 1631 {
 1632         struct resource *r;
 1633         bus_size_t       res_offset;
 1634         int              error;
 1635 
 1636         /* Map the target address */
 1637         error = bhndb_pci_probe_map(probe, addr, offset, width, &r,
 1638             &res_offset);
 1639         if (error) {
 1640                 device_printf(probe->dev, "error mapping %#jx+%#jx for "
 1641                     "reading: %d\n", addr, offset, error);
 1642                 return (UINT32_MAX);
 1643         }
 1644 
 1645         /* Perform read */
 1646         switch (width) {
 1647         case 1:
 1648                 return (bus_read_1(r, res_offset));
 1649         case 2:
 1650                 return (bus_read_2(r, res_offset));
 1651         case 4:
 1652                 return (bus_read_4(r, res_offset));
 1653         default:
 1654                 panic("unsupported width: %u", width);
 1655         }
 1656 }
 1657 
 1658 /**
 1659  * Initialize a new bhndb PCI bridge EROM I/O instance. All I/O will be
 1660  * performed using @p probe.
 1661  * 
 1662  * @param pio           The instance to be initialized.
 1663  * @param probe         The bhndb_pci probe state to be used to perform all
 1664  *                      I/O.
 1665  */
 1666 static void
 1667 bhndb_pci_eio_init(struct bhndb_pci_eio *pio, struct bhndb_pci_probe *probe)
 1668 {
 1669         memset(pio, 0, sizeof(*pio));
 1670 
 1671         pio->eio.map = bhndb_pci_eio_map;
 1672         pio->eio.tell = bhndb_pci_eio_tell;
 1673         pio->eio.read = bhndb_pci_eio_read;
 1674         pio->eio.fini = NULL;
 1675 
 1676         pio->mapped = false;
 1677         pio->addr = 0;
 1678         pio->size = 0;
 1679         pio->probe = probe;
 1680 }
 1681 
 1682 /* bhnd_erom_io_map() implementation */
 1683 static int
 1684 bhndb_pci_eio_map(struct bhnd_erom_io *eio, bhnd_addr_t addr,
 1685     bhnd_size_t size)
 1686 {
 1687         struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
 1688 
 1689         if (BHND_ADDR_MAX - addr < size)
 1690                 return (EINVAL); /* addr+size would overflow */
 1691 
 1692         pio->addr = addr;
 1693         pio->size = size;
 1694         pio->mapped = true;
 1695 
 1696         return (0);
 1697 }
 1698 
 1699 /* bhnd_erom_io_tell() implementation */
 1700 static int
 1701 bhndb_pci_eio_tell(struct bhnd_erom_io *eio, bhnd_addr_t *addr,
 1702     bhnd_size_t *size)
 1703 {
 1704         struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
 1705 
 1706         if (!pio->mapped)
 1707                 return (ENXIO);
 1708 
 1709         *addr = pio->addr;
 1710         *size = pio->size;
 1711 
 1712         return (0);
 1713 }
 1714 
 1715 /* bhnd_erom_io_read() implementation */
 1716 static uint32_t
 1717 bhndb_pci_eio_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
 1718 {
 1719         struct bhndb_pci_eio *pio = (struct bhndb_pci_eio *)eio;
 1720 
 1721         /* Must have a valid mapping */
 1722         if (!pio->mapped) 
 1723                 panic("no active mapping");
 1724 
 1725         /* The requested subrange must fall within the existing mapped range */
 1726         if (offset > pio->size ||
 1727             width > pio->size ||
 1728             pio->size - offset < width)
 1729         {
 1730                 panic("invalid offset %#jx", offset);
 1731         }
 1732 
 1733         return (bhndb_pci_probe_read(pio->probe, pio->addr, offset, width));
 1734 }
 1735 
 1736 static device_method_t bhndb_pci_methods[] = {
 1737         /* Device interface */
 1738         DEVMETHOD(device_probe,                         bhndb_pci_probe),
 1739         DEVMETHOD(device_attach,                        bhndb_pci_attach),
 1740         DEVMETHOD(device_resume,                        bhndb_pci_resume),
 1741         DEVMETHOD(device_suspend,                       bhndb_pci_suspend),
 1742         DEVMETHOD(device_detach,                        bhndb_pci_detach),
 1743 
 1744         /* BHNDB interface */
 1745         DEVMETHOD(bhndb_set_window_addr,                bhndb_pci_set_window_addr),
 1746         DEVMETHOD(bhndb_populate_board_info,            bhndb_pci_populate_board_info),
 1747         DEVMETHOD(bhndb_map_intr_isrc,                  bhndb_pci_map_intr_isrc),
 1748         DEVMETHOD(bhndb_route_interrupts,               bhndb_pci_route_interrupts),
 1749 
 1750         /* BHND PWRCTL hostb interface */
 1751         DEVMETHOD(bhnd_pwrctl_hostb_get_clksrc,         bhndb_pci_pwrctl_get_clksrc),
 1752         DEVMETHOD(bhnd_pwrctl_hostb_gate_clock,         bhndb_pci_pwrctl_gate_clock),
 1753         DEVMETHOD(bhnd_pwrctl_hostb_ungate_clock,       bhndb_pci_pwrctl_ungate_clock),
 1754 
 1755         DEVMETHOD_END
 1756 };
 1757 
 1758 DEFINE_CLASS_1(bhndb, bhndb_pci_driver, bhndb_pci_methods,
 1759     sizeof(struct bhndb_pci_softc), bhndb_driver);
 1760 
 1761 MODULE_VERSION(bhndb_pci, 1);
 1762 MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1);
 1763 MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1);
 1764 MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1);
 1765 MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1);

Cache object: 417ba0afe284803622883aa3dd676691


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