Lines Matching +full:memcpy +full:- +full:bus +full:- +full:width
1 /*-
2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
36 * PCI-specific implementation for the BHNDB bridge driver.
38 * Provides support for bridging from a PCI parent bus to a BHND-compatible
39 * bus (e.g. bcma or siba) via a Broadcom PCI core configured in end-point
42 * This driver handles all initial generic host-level PCI interactions with a
44 * bus has been enumerated, this driver works in tandem with a core-specific
50 #include <sys/bus.h>
96 bus_size_t offset, uint32_t value, u_int width);
98 bus_size_t offset, u_int width);
118 uint32_t value, u_int width);
120 bhnd_addr_t addr, bhnd_size_t offset, u_int width);
129 bhnd_size_t offset, u_int width);
154 * Provides early bus access to the bridged device's cores and core enumeration
169 struct bhnd_core_info *cores; /**< erom-owned core table */
183 /* Backplane interrupt flags must be routed via siba-specific
190 /* All PCI core revisions require the SRSH work-around */
196 /* All PCIe-G1 core revisions require the SRSH work-around */
214 if (bhnd_core_matches(ci, &entry->match))
238 if ((qtable = entry->quirks) == NULL)
244 if (!bhnd_chip_matches(cid, &q->chip_desc))
247 if (!bhnd_core_matches(ci, &q->core_desc))
250 quirks |= q->quirks;
280 /* The bus device class may inherit from 'pci' */
302 if ((entry = bhndb_pci_find_core(&probe->hostb_core)) == NULL) {
307 device_set_desc(dev, "PCI-BHND bridge");
309 /* fall-through */
331 if (pci_msi_count(sc->parent) < BHNDB_PCI_MSI_COUNT)
336 if ((error = pci_alloc_msi(sc->parent, &count))) {
337 device_printf(sc->dev, "failed to allocate MSI interrupts: "
344 pci_release_msi(sc->parent);
365 sc->dev = dev;
366 sc->parent = device_get_parent(dev);
367 sc->pci_devclass = bhndb_expected_pci_devclass(dev);
368 sc->pci_quirks = 0;
369 sc->set_regwin = NULL;
376 /* Enable PCI bus mastering */
377 pci_enable_busmaster(sc->parent);
380 if ((error = bhndb_enable_pci_clocks(sc->dev)))
384 error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass);
388 sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid,
389 &probe->hostb_core);
392 if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) {
393 sc->set_regwin = bhndb_pci_compat_setregwin;
395 sc->set_regwin = bhndb_pci_fast_setregwin;
408 if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) {
413 device_get_nameunit(sc->parent));
415 sc->msi_count = 0;
419 device_get_nameunit(sc->parent));
422 sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1,
424 if (sc->isrc == NULL) {
425 device_printf(sc->dev, "failed to allocate interrupt "
438 cid = probe->cid;
439 erom_class = probe->erom_class;
440 hostb_core = probe->hostb_core;
470 if (sc->isrc != NULL)
471 bhndb_free_intr_isrc(sc->isrc);
473 if (sc->msi_count > 0)
474 pci_release_msi(sc->parent);
482 bhndb_disable_pci_clocks(sc->dev);
484 pci_disable_busmaster(sc->parent);
508 if ((error = bhndb_disable_pci_clocks(sc->dev)))
512 bhndb_free_intr_isrc(sc->isrc);
515 if (sc->msi_count > 0)
516 pci_release_msi(sc->parent);
518 /* Disable PCI bus mastering */
519 pci_disable_busmaster(sc->parent);
542 device_printf(sc->dev, "found SPROM (%ju bytes)\n",
547 * before the bridged bhnd(4) bus is attached. */
548 child = BUS_ADD_CHILD(sc->dev,
549 BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY, "bhnd_nvram", -1);
551 device_printf(sc->dev, "failed to add sprom device\n");
558 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE;
563 device_printf(sc->dev,
579 bres = sc->bhndb.bus_res;
580 cfg = bres->cfg;
582 sprom_win = bhndb_regwin_find_type(cfg->register_windows,
599 r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, sprom_win);
602 return (rman_get_start(r) + sprom_win->win_offset);
619 sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4);
638 device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl);
645 sprom_sz = MIN(sprom_sz, sprom_win->win_size);
674 win = bhndb_regwin_find_core(sc->bhndb.bus_res->cfg->register_windows,
675 sc->pci_devclass, 0, BHND_PORT_DEVICE, 0, 0, offset, size);
677 device_printf(sc->dev, "missing PCI core register window\n");
682 r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, win);
684 device_printf(sc->dev, "missing PCI core register resource\n");
688 KASSERT(offset >= win->d.core.offset, ("offset %#jx outside of "
692 *res_offset = win->win_offset + (offset - win->d.core.offset);
703 * @param width item width (1, 2, or 4 bytes).
707 uint32_t value, u_int width)
713 error = bhndb_pci_get_core_regs(sc, offset, width, &r, &r_offset);
716 (uintmax_t)offset, width, error);
719 switch (width) {
730 panic("invalid width: %u", width);
740 * @param width item width (1, 2, or 4 bytes).
743 bhndb_pci_read_core(struct bhndb_pci_softc *sc, bus_size_t offset, u_int width)
749 error = bhndb_pci_get_core_regs(sc, offset, width, &r, &r_offset);
752 (uintmax_t)offset, width, error);
755 switch (width) {
763 panic("invalid width: %u", width);
768 * Fix-up power on defaults for SPROM-less devices.
770 * On SPROM-less devices, the PCI(e) cores will be initialized with their their
771 * Power-on-Reset defaults; this can leave the BHND_PCI_SRSH_PI value pointing
782 * 11:0 bits [11:0] of the PCI bus address
788 * 0x1000-0x17FF sprom shadow 0x800-0xFFF
789 * 0x1800-0x1DFF device registers 0x000-0x5FF
790 * 0x1E00+0x1FFF siba config registers 0xE00-0xFFF
792 * This function checks -- and if necessary, corrects -- the BHND_PCI_SRSH_PI
798 * Applies to all PCI and PCIe-G1 core revisions.
812 if ((sc->pci_quirks & BHNDB_PCI_QUIRK_SRSH_WAR) == 0)
817 md = bhnd_core_get_match_desc(&probe->hostb_core);
818 error = bhnd_erom_lookup_core_addr(probe->erom, &md, BHND_PORT_DEVICE,
821 device_printf(sc->dev, "no base address found for the PCI host "
854 if ((error = bhndb_enable_pci_clocks(sc->dev)))
870 if ((error = bhndb_disable_pci_clocks(sc->dev)))
882 return (sc->set_regwin(sc->dev, sc->parent, rw, addr));
886 * A siba(4) and bcma(4)-compatible bhndb_set_window_addr implementation.
902 if (rw->win_type != BHNDB_REGWIN_T_DYN)
905 reg = rw->d.dyn.cfg_offset;
921 * A bcma(4)-only bhndb_set_window_addr implementation.
927 /* The PCI bridge core only supports 32-bit addressing, regardless
928 * of the bus' support for 64-bit addressing */
932 switch (rw->win_type) {
935 if (addr % rw->win_size != 0)
938 pci_write_config(pci_dev, rw->d.dyn.cfg_offset, addr, 4);
957 * PCI subdevice to the SPROM-supplied boardtype.
963 * board-specific workarounds.
968 * explicit references to the SPROM-supplied boardtype(s) in our
971 if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) {
972 switch (info->board_type) {
977 info->board_type = 0; /* allow override below */
986 if (info->board_vendor == 0)
987 info->board_vendor = pci_get_subvendor(sc->parent);
989 if (info->board_type == 0)
990 info->board_type = pci_get_subdevice(sc->parent);
992 if (info->board_devid == 0)
993 info->board_devid = pci_get_device(sc->parent);
1034 * the idle low-power clock. Clocking must be bootstrapped at
1081 /* Clear any PCI 'sent target-abort' flag. */
1135 if (bhndb_is_pcie_attached(sc->dev))
1142 gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
1156 if (bhndb_is_pcie_attached(sc->dev))
1163 return (bhndb_disable_pci_clocks(sc->dev));
1173 if (bhndb_is_pcie_attached(sc->dev))
1180 return (bhndb_enable_pci_clocks(sc->dev));
1193 *isrc = sc->isrc;
1197 /* siba-specific implementation of BHNDB_ROUTE_INTERRUPTS() */
1205 KASSERT(sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC,
1212 if (ivec > (sizeof(sbintvec)*8) - 1 /* aka '31' */) {
1214 device_printf(sc->dev, "cannot route interrupts to high "
1241 if (sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC)
1255 intmask = pci_read_config(sc->parent, BHNDB_PCI_INT_MASK, 4);
1257 pci_write_config(sc->parent, BHNDB_PCI_INT_MASK, intmask, 4);
1276 * @retval non-zero if allocating the probe state fails, a regular
1298 p->dev = dev;
1299 p->pci_dev = parent_dev;
1304 p->m_win = NULL;
1305 p->m_res = NULL;
1306 p->m_valid = false;
1308 bhndb_pci_eio_init(&p->erom_io, p);
1309 eio = &p->erom_io.eio;
1316 error = bhndb_alloc_host_resources(&p->hr, dev, parent_dev, hwcfg);
1318 p->hr = NULL;
1322 /* Map the first bus core from our bridged bhnd(4) bus */
1329 p->erom_class = bhnd_erom_probe_driver_classes(
1330 device_get_devclass(dev), eio, hint, &p->cid);
1331 if (p->erom_class == NULL) {
1340 p->erom = bhnd_erom_alloc(p->erom_class, &p->cid, eio);
1341 if (p->erom == NULL) {
1352 error = bhnd_erom_get_core_table(p->erom, &p->cores, &p->ncores);
1354 device_printf(p->dev, "error fetching core table: %d\n",
1357 p->cores = NULL;
1362 error = bhndb_find_hostb_core(p->cores, p->ncores, hostb_devclass,
1363 &p->hostb_core);
1376 KASSERT(p->erom == NULL, ("I/O instance will be freed by "
1382 if (p->erom != NULL) {
1383 if (p->cores != NULL)
1384 bhnd_erom_free_core_table(p->erom, p->cores);
1386 bhnd_erom_free(p->erom);
1388 KASSERT(p->cores == NULL, ("cannot free erom-owned core table "
1392 if (p->hr != NULL)
1393 bhndb_release_host_resources(p->hr);
1406 bhnd_erom_free_core_table(probe->erom, probe->cores);
1407 bhnd_erom_free(probe->erom);
1408 bhndb_release_host_resources(probe->hr);
1423 * @retval non-zero if enumerating the bridged bhnd(4) bus fails, a regular
1430 size_t len = sizeof(**cores) * probe->ncores;
1433 memcpy(*cores, probe->cores, len);
1435 *ncores = probe->ncores;
1459 if (!probe->m_valid)
1462 KASSERT(probe->m_win != NULL, ("missing register window"));
1463 KASSERT(probe->m_res != NULL, ("missing regwin resource"));
1464 KASSERT(probe->m_win->win_type == BHNDB_REGWIN_T_DYN,
1465 ("unexpected window type %d", probe->m_win->win_type));
1467 if (addr < probe->m_target)
1470 if (addr >= probe->m_target + probe->m_win->win_size)
1473 if ((probe->m_target + probe->m_win->win_size) - addr < size)
1492 * @retval non-zero if an error occurs adjusting the backing dynamic
1506 if (BHND_SIZE_MAX - offset < addr) {
1507 device_printf(probe->dev, "invalid offset %#jx+%#jx\n", addr,
1516 *res = probe->m_res;
1517 *res_offset = (addr - probe->m_target) +
1518 probe->m_win->win_offset;
1524 regwin_table = probe->hr->cfg->register_windows;
1528 device_printf(probe->dev, "unable to map %#jx+%#jx; no "
1535 regwin_res = bhndb_host_resource_for_regwin(probe->hr, regwin);
1537 device_printf(probe->dev, "unable to map %#jx+%#jx; no "
1542 /* Page-align the target address */
1543 target = addr - (addr % regwin->win_size);
1546 error = bhndb_pci_compat_setregwin(probe->dev, probe->pci_dev,
1549 device_printf(probe->dev, "failed to configure dynamic "
1555 probe->m_win = regwin;
1556 probe->m_res = regwin_res;
1557 probe->m_addr = addr;
1558 probe->m_size = size;
1559 probe->m_target = target;
1560 probe->m_valid = true;
1563 *res_offset = (addr - target) + regwin->win_offset;
1580 * @param width The data item width (1, 2, or 4 bytes).
1584 bhnd_size_t offset, uint32_t value, u_int width)
1591 error = bhndb_pci_probe_map(probe, addr, offset, width, &r,
1594 device_printf(probe->dev, "error mapping %#jx+%#jx for "
1600 switch (width) {
1608 panic("unsupported width: %u", width);
1622 * @p width bytes.
1623 * @param width Item width (1, 2, or 4 bytes).
1627 bhnd_size_t offset, u_int width)
1634 error = bhndb_pci_probe_map(probe, addr, offset, width, &r,
1637 device_printf(probe->dev, "error mapping %#jx+%#jx for "
1643 switch (width) {
1651 panic("unsupported width: %u", width);
1668 pio->eio.map = bhndb_pci_eio_map;
1669 pio->eio.tell = bhndb_pci_eio_tell;
1670 pio->eio.read = bhndb_pci_eio_read;
1671 pio->eio.fini = NULL;
1673 pio->mapped = false;
1674 pio->addr = 0;
1675 pio->size = 0;
1676 pio->probe = probe;
1686 if (BHND_ADDR_MAX - addr < size)
1689 pio->addr = addr;
1690 pio->size = size;
1691 pio->mapped = true;
1703 if (!pio->mapped)
1706 *addr = pio->addr;
1707 *size = pio->size;
1714 bhndb_pci_eio_read(struct bhnd_erom_io *eio, bhnd_size_t offset, u_int width)
1719 if (!pio->mapped)
1723 if (offset > pio->size ||
1724 width > pio->size ||
1725 pio->size - offset < width)
1730 return (bhndb_pci_probe_read(pio->probe, pio->addr, offset, width));