Lines Matching +full:probe +full:- +full:reset

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
101 struct bhndb_pci_probe *probe);
106 static int bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe,
108 static void bhndb_pci_probe_free(struct bhndb_pci_probe *probe);
111 struct bhndb_pci_probe *probe,
123 struct bhndb_pci_probe *probe);
150 struct bhndb_pci_probe *probe; /**< borrowed probe reference */ member
157 * May be safely used during probe or early device attach, prior to calling
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)) in bhndb_pci_find_core()
238 if ((qtable = entry->quirks) == NULL) in bhndb_pci_get_core_quirks()
244 if (!bhnd_chip_matches(cid, &q->chip_desc)) in bhndb_pci_get_core_quirks()
247 if (!bhnd_core_matches(ci, &q->core_desc)) in bhndb_pci_get_core_quirks()
250 quirks |= q->quirks; in bhndb_pci_get_core_quirks()
264 struct bhndb_pci_probe *probe; in bhndb_pci_probe() local
271 probe = NULL; in bhndb_pci_probe()
298 if ((error = bhndb_pci_probe_alloc(&probe, dev, hostb_devclass))) in bhndb_pci_probe()
302 if ((entry = bhndb_pci_find_core(&probe->hostb_core)) == NULL) { in bhndb_pci_probe()
307 device_set_desc(dev, "PCI-BHND bridge"); in bhndb_pci_probe()
309 /* fall-through */ in bhndb_pci_probe()
313 if (probe != NULL) in bhndb_pci_probe()
314 bhndb_pci_probe_free(probe); in bhndb_pci_probe()
331 if (pci_msi_count(sc->parent) < BHNDB_PCI_MSI_COUNT) in bhndb_pci_alloc_msi()
336 if ((error = pci_alloc_msi(sc->parent, &count))) { in bhndb_pci_alloc_msi()
337 device_printf(sc->dev, "failed to allocate MSI interrupts: " in bhndb_pci_alloc_msi()
344 pci_release_msi(sc->parent); in bhndb_pci_alloc_msi()
359 struct bhndb_pci_probe *probe; in bhndb_pci_attach() local
365 sc->dev = dev; in bhndb_pci_attach()
366 sc->parent = device_get_parent(dev); in bhndb_pci_attach()
367 sc->pci_devclass = bhndb_expected_pci_devclass(dev); in bhndb_pci_attach()
368 sc->pci_quirks = 0; in bhndb_pci_attach()
369 sc->set_regwin = NULL; in bhndb_pci_attach()
373 probe = NULL; in bhndb_pci_attach()
377 pci_enable_busmaster(sc->parent); in bhndb_pci_attach()
380 if ((error = bhndb_enable_pci_clocks(sc->dev))) in bhndb_pci_attach()
384 error = bhndb_pci_probe_alloc(&probe, dev, sc->pci_devclass); in bhndb_pci_attach()
388 sc->pci_quirks = bhndb_pci_get_core_quirks(&probe->cid, in bhndb_pci_attach()
389 &probe->hostb_core); in bhndb_pci_attach()
392 if (probe->cid.chip_type == BHND_CHIPTYPE_SIBA) { in bhndb_pci_attach()
393 sc->set_regwin = bhndb_pci_compat_setregwin; in bhndb_pci_attach()
395 sc->set_regwin = bhndb_pci_fast_setregwin; in bhndb_pci_attach()
404 if ((error = bhndb_pci_srsh_pi_war(sc, probe))) in bhndb_pci_attach()
408 if (bhndb_pci_alloc_msi(sc, &sc->msi_count) == 0) { in bhndb_pci_attach()
413 device_get_nameunit(sc->parent)); in bhndb_pci_attach()
415 sc->msi_count = 0; in bhndb_pci_attach()
419 device_get_nameunit(sc->parent)); in bhndb_pci_attach()
422 sc->isrc = bhndb_alloc_intr_isrc(sc->parent, irq_rid, 0, RM_MAX_END, 1, in bhndb_pci_attach()
424 if (sc->isrc == NULL) { in bhndb_pci_attach()
425 device_printf(sc->dev, "failed to allocate interrupt " in bhndb_pci_attach()
432 * Copy out the probe results and then free our probe state, releasing in bhndb_pci_attach()
438 cid = probe->cid; in bhndb_pci_attach()
439 erom_class = probe->erom_class; in bhndb_pci_attach()
440 hostb_core = probe->hostb_core; in bhndb_pci_attach()
442 error = bhndb_pci_probe_copy_core_table(probe, &cores, &ncores); in bhndb_pci_attach()
448 bhndb_pci_probe_free(probe); in bhndb_pci_attach()
449 probe = NULL; in bhndb_pci_attach()
460 /* Probe and attach our children */ in bhndb_pci_attach()
470 if (sc->isrc != NULL) in bhndb_pci_attach()
471 bhndb_free_intr_isrc(sc->isrc); in bhndb_pci_attach()
473 if (sc->msi_count > 0) in bhndb_pci_attach()
474 pci_release_msi(sc->parent); in bhndb_pci_attach()
479 if (probe != NULL) in bhndb_pci_attach()
480 bhndb_pci_probe_free(probe); in bhndb_pci_attach()
482 bhndb_disable_pci_clocks(sc->dev); in bhndb_pci_attach()
484 pci_disable_busmaster(sc->parent); in bhndb_pci_attach()
508 if ((error = bhndb_disable_pci_clocks(sc->dev))) in bhndb_pci_detach()
512 bhndb_free_intr_isrc(sc->isrc); in bhndb_pci_detach()
515 if (sc->msi_count > 0) in bhndb_pci_detach()
516 pci_release_msi(sc->parent); in bhndb_pci_detach()
519 pci_disable_busmaster(sc->parent); in bhndb_pci_detach()
542 device_printf(sc->dev, "found SPROM (%ju bytes)\n", in bhndb_pci_add_children()
548 child = BUS_ADD_CHILD(sc->dev, in bhndb_pci_add_children()
549 BHND_PROBE_ROOT + BHND_PROBE_ORDER_EARLY, "bhnd_nvram", -1); in bhndb_pci_add_children()
551 device_printf(sc->dev, "failed to add sprom device\n"); in bhndb_pci_add_children()
558 dinfo->addrspace = BHNDB_ADDRSPACE_NATIVE; in bhndb_pci_add_children()
563 device_printf(sc->dev, in bhndb_pci_add_children()
579 bres = sc->bhndb.bus_res; in bhndb_pci_sprom_regwin()
580 cfg = bres->cfg; in bhndb_pci_sprom_regwin()
582 sprom_win = bhndb_regwin_find_type(cfg->register_windows, in bhndb_pci_sprom_regwin()
599 r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, sprom_win); in bhndb_pci_sprom_addr()
602 return (rman_get_start(r) + sprom_win->win_offset); in bhndb_pci_sprom_addr()
619 sctl = pci_read_config(sc->parent, BHNDB_PCI_SPROM_CONTROL, 4); in bhndb_pci_sprom_size()
638 device_printf(sc->dev, "invalid PCI sprom size 0x%x\n", sctl); in bhndb_pci_sprom_size()
645 sprom_sz = MIN(sprom_sz, sprom_win->win_size); in bhndb_pci_sprom_size()
674 win = bhndb_regwin_find_core(sc->bhndb.bus_res->cfg->register_windows, in bhndb_pci_get_core_regs()
675 sc->pci_devclass, 0, BHND_PORT_DEVICE, 0, 0, offset, size); in bhndb_pci_get_core_regs()
677 device_printf(sc->dev, "missing PCI core register window\n"); in bhndb_pci_get_core_regs()
682 r = bhndb_host_resource_for_regwin(sc->bhndb.bus_res->res, win); in bhndb_pci_get_core_regs()
684 device_printf(sc->dev, "missing PCI core register resource\n"); in bhndb_pci_get_core_regs()
688 KASSERT(offset >= win->d.core.offset, ("offset %#jx outside of " in bhndb_pci_get_core_regs()
692 *res_offset = win->win_offset + (offset - win->d.core.offset); in bhndb_pci_get_core_regs()
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
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.
802 struct bhndb_pci_probe *probe) in bhndb_pci_srsh_pi_war() argument
812 if ((sc->pci_quirks & BHNDB_PCI_QUIRK_SRSH_WAR) == 0) in bhndb_pci_srsh_pi_war()
817 md = bhnd_core_get_match_desc(&probe->hostb_core); in bhndb_pci_srsh_pi_war()
818 error = bhnd_erom_lookup_core_addr(probe->erom, &md, BHND_PORT_DEVICE, in bhndb_pci_srsh_pi_war()
821 device_printf(sc->dev, "no base address found for the PCI host " in bhndb_pci_srsh_pi_war()
828 val = bhndb_pci_probe_read(probe, pci_addr, srsh_offset, sizeof(val)); in bhndb_pci_srsh_pi_war()
838 bhndb_pci_probe_write(probe, pci_addr, srsh_offset, val, in bhndb_pci_srsh_pi_war()
854 if ((error = bhndb_enable_pci_clocks(sc->dev))) in bhndb_pci_resume()
870 if ((error = bhndb_disable_pci_clocks(sc->dev))) in bhndb_pci_suspend()
882 return (sc->set_regwin(sc->dev, sc->parent, rw, addr)); in bhndb_pci_set_window_addr()
886 * A siba(4) and bcma(4)-compatible bhndb_set_window_addr implementation.
902 if (rw->win_type != BHNDB_REGWIN_T_DYN) in bhndb_pci_compat_setregwin()
905 reg = rw->d.dyn.cfg_offset; in bhndb_pci_compat_setregwin()
921 * A bcma(4)-only bhndb_set_window_addr implementation.
927 /* The PCI bridge core only supports 32-bit addressing, regardless in bhndb_pci_fast_setregwin()
928 * of the bus' support for 64-bit addressing */ in bhndb_pci_fast_setregwin()
932 switch (rw->win_type) { in bhndb_pci_fast_setregwin()
935 if (addr % rw->win_size != 0) in bhndb_pci_fast_setregwin()
938 pci_write_config(pci_dev, rw->d.dyn.cfg_offset, addr, 4); in bhndb_pci_fast_setregwin()
957 * PCI subdevice to the SPROM-supplied boardtype. in bhndb_pci_populate_board_info()
963 * board-specific workarounds. in bhndb_pci_populate_board_info()
968 * explicit references to the SPROM-supplied boardtype(s) in our in bhndb_pci_populate_board_info()
971 if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) { in bhndb_pci_populate_board_info()
972 switch (info->board_type) { in bhndb_pci_populate_board_info()
977 info->board_type = 0; /* allow override below */ in bhndb_pci_populate_board_info()
986 if (info->board_vendor == 0) in bhndb_pci_populate_board_info()
987 info->board_vendor = pci_get_subvendor(sc->parent); in bhndb_pci_populate_board_info()
989 if (info->board_type == 0) in bhndb_pci_populate_board_info()
990 info->board_type = pci_get_subdevice(sc->parent); in bhndb_pci_populate_board_info()
992 if (info->board_devid == 0) in bhndb_pci_populate_board_info()
993 info->board_devid = pci_get_device(sc->parent); in bhndb_pci_populate_board_info()
1034 * the idle low-power clock. Clocking must be bootstrapped at
1076 /* Reset PLL_OFF */ in bhndb_enable_pci_clocks()
1081 /* Clear any PCI 'sent target-abort' flag. */ in bhndb_enable_pci_clocks()
1135 if (bhndb_is_pcie_attached(sc->dev)) in bhndb_pci_pwrctl_get_clksrc()
1142 gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4); in bhndb_pci_pwrctl_get_clksrc()
1156 if (bhndb_is_pcie_attached(sc->dev)) in bhndb_pci_pwrctl_gate_clock()
1163 return (bhndb_disable_pci_clocks(sc->dev)); in bhndb_pci_pwrctl_gate_clock()
1173 if (bhndb_is_pcie_attached(sc->dev)) in bhndb_pci_pwrctl_ungate_clock()
1180 return (bhndb_enable_pci_clocks(sc->dev)); in bhndb_pci_pwrctl_ungate_clock()
1193 *isrc = sc->isrc; in bhndb_pci_map_intr_isrc()
1197 /* siba-specific implementation of BHNDB_ROUTE_INTERRUPTS() */
1205 KASSERT(sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC, in bhndb_pci_route_siba_interrupts()
1212 if (ivec > (sizeof(sbintvec)*8) - 1 /* aka '31' */) { in bhndb_pci_route_siba_interrupts()
1214 device_printf(sc->dev, "cannot route interrupts to high " in bhndb_pci_route_siba_interrupts()
1241 if (sc->pci_quirks & BHNDB_PCI_QUIRK_SIBA_INTVEC) in bhndb_pci_route_interrupts()
1255 intmask = pci_read_config(sc->parent, BHNDB_PCI_INT_MASK, 4); in bhndb_pci_route_interrupts()
1257 pci_write_config(sc->parent, BHNDB_PCI_INT_MASK, intmask, 4); in bhndb_pci_route_interrupts()
1266 * and return a new bhndb_pci probe state instance.
1268 * On success, the caller assumes ownership of the returned probe instance, and
1271 * @param[out] probe On success, the newly allocated probe instance.
1276 * @retval non-zero if allocating the probe state fails, a regular
1284 bhndb_pci_probe_alloc(struct bhndb_pci_probe **probe, device_t dev, in bhndb_pci_probe_alloc() argument
1298 p->dev = dev; in bhndb_pci_probe_alloc()
1299 p->pci_dev = parent_dev; in bhndb_pci_probe_alloc()
1304 p->m_win = NULL; in bhndb_pci_probe_alloc()
1305 p->m_res = NULL; in bhndb_pci_probe_alloc()
1306 p->m_valid = false; in bhndb_pci_probe_alloc()
1308 bhndb_pci_eio_init(&p->erom_io, p); in bhndb_pci_probe_alloc()
1309 eio = &p->erom_io.eio; in bhndb_pci_probe_alloc()
1316 error = bhndb_alloc_host_resources(&p->hr, dev, parent_dev, hwcfg); in bhndb_pci_probe_alloc()
1318 p->hr = NULL; in bhndb_pci_probe_alloc()
1328 /* Probe for a usable EROM class, and read the chip identifier */ in bhndb_pci_probe_alloc()
1329 p->erom_class = bhnd_erom_probe_driver_classes( in bhndb_pci_probe_alloc()
1330 device_get_devclass(dev), eio, hint, &p->cid); in bhndb_pci_probe_alloc()
1331 if (p->erom_class == NULL) { in bhndb_pci_probe_alloc()
1340 p->erom = bhnd_erom_alloc(p->erom_class, &p->cid, eio); in bhndb_pci_probe_alloc()
1341 if (p->erom == NULL) { in bhndb_pci_probe_alloc()
1352 error = bhnd_erom_get_core_table(p->erom, &p->cores, &p->ncores); in bhndb_pci_probe_alloc()
1354 device_printf(p->dev, "error fetching core table: %d\n", in bhndb_pci_probe_alloc()
1357 p->cores = NULL; in bhndb_pci_probe_alloc()
1362 error = bhndb_find_hostb_core(p->cores, p->ncores, hostb_devclass, in bhndb_pci_probe_alloc()
1363 &p->hostb_core); in bhndb_pci_probe_alloc()
1371 *probe = p; in bhndb_pci_probe_alloc()
1376 KASSERT(p->erom == NULL, ("I/O instance will be freed by " in bhndb_pci_probe_alloc()
1382 if (p->erom != NULL) { in bhndb_pci_probe_alloc()
1383 if (p->cores != NULL) in bhndb_pci_probe_alloc()
1384 bhnd_erom_free_core_table(p->erom, p->cores); in bhndb_pci_probe_alloc()
1386 bhnd_erom_free(p->erom); in bhndb_pci_probe_alloc()
1388 KASSERT(p->cores == NULL, ("cannot free erom-owned core table " in bhndb_pci_probe_alloc()
1392 if (p->hr != NULL) in bhndb_pci_probe_alloc()
1393 bhndb_release_host_resources(p->hr); in bhndb_pci_probe_alloc()
1401 * Free the given @p probe instance and any associated host bridge resources.
1404 bhndb_pci_probe_free(struct bhndb_pci_probe *probe) in bhndb_pci_probe_free() argument
1406 bhnd_erom_free_core_table(probe->erom, probe->cores); in bhndb_pci_probe_free()
1407 bhnd_erom_free(probe->erom); in bhndb_pci_probe_free()
1408 bhndb_release_host_resources(probe->hr); in bhndb_pci_probe_free()
1409 free(probe, M_BHND); in bhndb_pci_probe_free()
1413 * Return a copy of probed core table from @p probe.
1415 * @param probe The probe instance.
1423 * @retval non-zero if enumerating the bridged bhnd(4) bus fails, a regular
1427 bhndb_pci_probe_copy_core_table(struct bhndb_pci_probe *probe, in bhndb_pci_probe_copy_core_table() argument
1430 size_t len = sizeof(**cores) * probe->ncores; in bhndb_pci_probe_copy_core_table()
1433 memcpy(*cores, probe->cores, len); in bhndb_pci_probe_copy_core_table()
1435 *ncores = probe->ncores; in bhndb_pci_probe_copy_core_table()
1453 * backing @p probe.
1456 bhndb_pci_probe_has_mapping(struct bhndb_pci_probe *probe, bhnd_addr_t addr, in bhndb_pci_probe_has_mapping() argument
1459 if (!probe->m_valid) in bhndb_pci_probe_has_mapping()
1462 KASSERT(probe->m_win != NULL, ("missing register window")); in bhndb_pci_probe_has_mapping()
1463 KASSERT(probe->m_res != NULL, ("missing regwin resource")); in bhndb_pci_probe_has_mapping()
1464 KASSERT(probe->m_win->win_type == BHNDB_REGWIN_T_DYN, in bhndb_pci_probe_has_mapping()
1465 ("unexpected window type %d", probe->m_win->win_type)); in bhndb_pci_probe_has_mapping()
1467 if (addr < probe->m_target) in bhndb_pci_probe_has_mapping()
1470 if (addr >= probe->m_target + probe->m_win->win_size) in bhndb_pci_probe_has_mapping()
1473 if ((probe->m_target + probe->m_win->win_size) - addr < size) in bhndb_pci_probe_has_mapping()
1480 * Attempt to adjust the dynamic register window backing @p probe to permit
1483 * @param probe The bhndb_pci probe state to be modified.
1492 * @retval non-zero if an error occurs adjusting the backing dynamic
1496 bhndb_pci_probe_map(struct bhndb_pci_probe *probe, bhnd_addr_t addr, in bhndb_pci_probe_map() argument
1506 if (BHND_SIZE_MAX - offset < addr) { in bhndb_pci_probe_map()
1507 device_printf(probe->dev, "invalid offset %#jx+%#jx\n", addr, in bhndb_pci_probe_map()
1515 if (bhndb_pci_probe_has_mapping(probe, addr, size)) { in bhndb_pci_probe_map()
1516 *res = probe->m_res; in bhndb_pci_probe_map()
1517 *res_offset = (addr - probe->m_target) + in bhndb_pci_probe_map()
1518 probe->m_win->win_offset; in bhndb_pci_probe_map()
1524 regwin_table = probe->hr->cfg->register_windows; in bhndb_pci_probe_map()
1528 device_printf(probe->dev, "unable to map %#jx+%#jx; no " in bhndb_pci_probe_map()
1535 regwin_res = bhndb_host_resource_for_regwin(probe->hr, regwin); in bhndb_pci_probe_map()
1537 device_printf(probe->dev, "unable to map %#jx+%#jx; no " in bhndb_pci_probe_map()
1542 /* Page-align the target address */ in bhndb_pci_probe_map()
1543 target = addr - (addr % regwin->win_size); in bhndb_pci_probe_map()
1546 error = bhndb_pci_compat_setregwin(probe->dev, probe->pci_dev, in bhndb_pci_probe_map()
1549 device_printf(probe->dev, "failed to configure dynamic " in bhndb_pci_probe_map()
1555 probe->m_win = regwin; in bhndb_pci_probe_map()
1556 probe->m_res = regwin_res; in bhndb_pci_probe_map()
1557 probe->m_addr = addr; in bhndb_pci_probe_map()
1558 probe->m_size = size; in bhndb_pci_probe_map()
1559 probe->m_target = target; in bhndb_pci_probe_map()
1560 probe->m_valid = true; in bhndb_pci_probe_map()
1563 *res_offset = (addr - target) + regwin->win_offset; in bhndb_pci_probe_map()
1574 * @param probe The bhndb_pci probe state to be used to perform the
1583 bhndb_pci_probe_write(struct bhndb_pci_probe *probe, bhnd_addr_t addr, in bhndb_pci_probe_write() argument
1591 error = bhndb_pci_probe_map(probe, addr, offset, width, &r, in bhndb_pci_probe_write()
1594 device_printf(probe->dev, "error mapping %#jx+%#jx for " in bhndb_pci_probe_write()
1618 * @param probe The bhndb_pci probe state to be used to perform the
1626 bhndb_pci_probe_read(struct bhndb_pci_probe *probe, bhnd_addr_t addr, in bhndb_pci_probe_read() argument
1634 error = bhndb_pci_probe_map(probe, addr, offset, width, &r, in bhndb_pci_probe_read()
1637 device_printf(probe->dev, "error mapping %#jx+%#jx for " in bhndb_pci_probe_read()
1657 * performed using @p probe.
1660 * @param probe The bhndb_pci probe state to be used to perform all
1664 bhndb_pci_eio_init(struct bhndb_pci_eio *pio, struct bhndb_pci_probe *probe) in bhndb_pci_eio_init() argument
1668 pio->eio.map = bhndb_pci_eio_map; in bhndb_pci_eio_init()
1669 pio->eio.tell = bhndb_pci_eio_tell; in bhndb_pci_eio_init()
1670 pio->eio.read = bhndb_pci_eio_read; in bhndb_pci_eio_init()
1671 pio->eio.fini = NULL; in bhndb_pci_eio_init()
1673 pio->mapped = false; in bhndb_pci_eio_init()
1674 pio->addr = 0; in bhndb_pci_eio_init()
1675 pio->size = 0; in bhndb_pci_eio_init()
1676 pio->probe = probe; in bhndb_pci_eio_init()
1686 if (BHND_ADDR_MAX - addr < size) in bhndb_pci_eio_map()
1689 pio->addr = addr; in bhndb_pci_eio_map()
1690 pio->size = size; in bhndb_pci_eio_map()
1691 pio->mapped = true; in bhndb_pci_eio_map()
1703 if (!pio->mapped) in bhndb_pci_eio_tell()
1706 *addr = pio->addr; in bhndb_pci_eio_tell()
1707 *size = pio->size; in bhndb_pci_eio_tell()
1719 if (!pio->mapped) in bhndb_pci_eio_read()
1723 if (offset > pio->size || in bhndb_pci_eio_read()
1724 width > pio->size || in bhndb_pci_eio_read()
1725 pio->size - offset < width) in bhndb_pci_eio_read()
1730 return (bhndb_pci_probe_read(pio->probe, pio->addr, offset, width)); in bhndb_pci_eio_read()