Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F131725100
D6377.id16435.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
84 KB
Referenced Files
None
Subscribers
None
D6377.id16435.diff
View Options
Index: sys/conf/files
===================================================================
--- sys/conf/files
+++ sys/conf/files
@@ -1142,6 +1142,9 @@
dev/bhnd/cores/pci/bhnd_pci.c optional bhndbus pci | bhnd pci
dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndbus pci | bhndb pci
dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci
+dev/bhnd/cores/pcie2/bhnd_pcie2.c optional bhndbus pci | bhnd pci
+dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c optional bhndbus pci | bhndb pci
+dev/bhnd/cores/pcie2/bhnd_pcie2b.c optional bhnd_pcie2b bhnd pci
dev/bhnd/nvram/bhnd_nvram_if.m optional bhndbus | bhnd
dev/bhnd/nvram/bhnd_sprom.c optional bhndbus | bhnd
dev/bhnd/nvram/nvram_subr.c optional bhndbus | bhnd
Index: sys/dev/bhnd/bhnd.h
===================================================================
--- sys/dev/bhnd/bhnd.h
+++ sys/dev/bhnd/bhnd.h
@@ -318,8 +318,8 @@
.match_bvendor = 1, .board_vendor = _vend
/** Set the required board type within a bhnd_chip_match instance */
-#define BHND_CHIP_BT(_btype) \
- .match_btype = 1, .board_type = BHND_BOARD_BCM ## _btype
+#define BHND_CHIP_BTYPE(_btype) \
+ .match_btype = 1, .board_type = BHND_BOARD_ ## _btype
/** Set the required SROM revision range within a bhnd_chip_match instance */
#define BHND_CHIP_SROMREV(_rev) \
@@ -331,7 +331,7 @@
/** Set the required board vendor and type within a bhnd_chip_match instance */
#define BHND_CHIP_BVT(_vend, _type) \
- BHND_CHIP_BVEND(_vend), BHND_CHIP_BTYPE(_type)
+ BHND_CHIP_BVENDOR(_vend), BHND_CHIP_BTYPE(_type)
/** Set the required board vendor, type, and revision within a bhnd_chip_match
* instance */
@@ -429,6 +429,9 @@
device_t bhnd_find_child(device_t dev,
bhnd_devclass_t class, int unit);
+device_t bhnd_find_bridge_root(device_t dev,
+ devclass_t bus_class);
+
const struct bhnd_core_info *bhnd_match_core(
const struct bhnd_core_info *cores,
u_int num_cores,
Index: sys/dev/bhnd/bhnd_ids.h
===================================================================
--- sys/dev/bhnd/bhnd_ids.h
+++ sys/dev/bhnd/bhnd_ids.h
@@ -26,8 +26,6 @@
#ifndef _BHND_BHND_IDS_H_
#define _BHND_BHND_IDS_H_
-
-
/*
* JEDEC JEP-106 Core Vendor IDs
*
@@ -851,12 +849,12 @@
#define BHND_BOARD_BU4785 0x0478
/* 4321 boards */
-#define BHND_BOARD_BU4321 0x046b
-#define BHND_BOARD_BU4321E 0x047c
-#define BHND_BOARD_MP4321 0x046c
-#define BHND_BOARD_CB2_4321 0x046d
-#define BHND_BOARD_CB2_4321_AG 0x0066
-#define BHND_BOARD_MC4321 0x046e
+#define BHND_BOARD_BCM4321BU 0x046b
+#define BHND_BOARD_BCM4321BUE 0x047c
+#define BHND_BOARD_BCM4321MP 0x046c
+#define BHND_BOARD_BCM4321CB2 0x046d
+#define BHND_BOARD_BCM4321CB2_AG 0x0066
+#define BHND_BOARD_BCM4321MC 0x046e
/* 4328 boards */
#define BHND_BOARD_BU4328 0x0481
Index: sys/dev/bhnd/bhnd_subr.c
===================================================================
--- sys/dev/bhnd/bhnd_subr.c
+++ sys/dev/bhnd/bhnd_subr.c
@@ -350,6 +350,56 @@
}
/**
+ * Walk up the bhnd device hierarchy to locate the root device
+ * to which the bhndb bridge is attached.
+ *
+ * This can be used from within bhnd host bridge drivers to locate the
+ * actual upstream host device.
+ *
+ * @param dev A bhnd device.
+ * @param bus_class The expected bus (e.g. "pci") to which the bridge root
+ * should be attached.
+ *
+ * @retval device_t if a matching parent device is found.
+ * @retval NULL @p dev is not attached via a bhndb bus
+ * @retval NULL no parent device is attached via @p bus_class.
+ */
+device_t
+bhnd_find_bridge_root(device_t dev, devclass_t bus_class)
+{
+ devclass_t bhndb_class;
+ device_t parent;
+
+ KASSERT(device_get_devclass(device_get_parent(dev)) == bhnd_devclass,
+ ("%s not a bhnd device", device_get_nameunit(dev)));
+
+ bhndb_class = devclass_find("bhndb");
+
+ /* Walk the device tree until we hit a bridge */
+ parent = dev;
+ while ((parent = device_get_parent(parent)) != NULL) {
+ if (device_get_devclass(parent) == bhndb_class)
+ break;
+ }
+
+ /* No bridge? */
+ if (parent == NULL)
+ return (NULL);
+
+ /* Search for a parent attached to the expected bus class */
+ while ((parent = device_get_parent(parent)) != NULL) {
+ device_t bus;
+
+ bus = device_get_parent(parent);
+ if (bus != NULL && device_get_devclass(bus) == bus_class)
+ return (parent);
+ }
+
+ /* Not found */
+ return (NULL);
+}
+
+/**
* Find the first core in @p cores that matches @p desc.
*
* @param cores The table to search.
Index: sys/dev/bhnd/bhndb/bhndb_pci.c
===================================================================
--- sys/dev/bhnd/bhndb/bhndb_pci.c
+++ sys/dev/bhnd/bhndb/bhndb_pci.c
@@ -37,9 +37,10 @@
* bus (e.g. bcma or siba) via a Broadcom PCI core configured in end-point
* mode.
*
- * This driver handles all host-level PCI interactions with a PCI/PCIe bridge
- * core operating in endpoint mode. On the bridged bhnd bus, the PCI core
- * device will be managed by a bhnd_pci_hostb driver.
+ * This driver handles all initial generic host-level PCI interactions with a
+ * PCI/PCIe bridge core operating in endpoint mode. Once the bridged bhnd(4)
+ * bus has been enumerated, this driver works in tandem with a core-specific
+ * bhnd_pci_hostb driver to manage the PCI core.
*/
#include <sys/param.h>
@@ -482,6 +483,35 @@
sc = device_get_softc(dev);
+ /*
+ * On a subset of Apple BCM4360 modules, always prefer the
+ * PCI subdevice to the SPROM-supplied boardtype.
+ *
+ * TODO:
+ *
+ * Broadcom's own drivers implement this override, and then later use
+ * the remapped BCM4360 board type to determine the required
+ * board-specific workarounds.
+ *
+ * Without access to this hardware, it's unclear why this mapping
+ * is done, and we must do the same. If we can survey the hardware
+ * in question, it may be possible to replace this behavior with
+ * explicit references to the SPROM-supplied boardtype(s) in our
+ * quirk definitions.
+ */
+ if (pci_get_subvendor(sc->parent) == PCI_VENDOR_APPLE) {
+ switch (info->board_type) {
+ case BHND_BOARD_BCM94360X29C:
+ case BHND_BOARD_BCM94360X29CP2:
+ case BHND_BOARD_BCM94360X51:
+ case BHND_BOARD_BCM94360X51P2:
+ info->board_type = 0; /* allow override below */
+ break;
+ default:
+ break;
+ }
+ }
+
/* If NVRAM did not supply vendor/type info, provide the PCI
* subvendor/subdevice values. */
if (info->board_vendor == 0)
@@ -560,10 +590,6 @@
if (sc->pci_devclass != BHND_DEVCLASS_PCI)
return (0);
- // TODO: Check board flags for BFL2_XTALBUFOUTEN?
- // TODO: Check PCI core revision?
- // TODO: Switch to 'slow' clock?
-
/* Fetch current config */
gpio_out = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUT, 4);
gpio_en = pci_read_config(sc->parent, BHNDB_PCI_GPIO_OUTEN, 4);
@@ -601,6 +627,7 @@
MODULE_VERSION(bhndb_pci, 1);
MODULE_DEPEND(bhndb_pci, bhnd_pci_hostb, 1, 1, 1);
+MODULE_DEPEND(bhndb_pci, bhnd_pcie2_hostb, 1, 1, 1);
MODULE_DEPEND(bhndb_pci, pci, 1, 1, 1);
MODULE_DEPEND(bhndb_pci, bhndb, 1, 1, 1);
MODULE_DEPEND(bhndb_pci, bhnd, 1, 1, 1);
Index: sys/dev/bhnd/bhndb/bhndb_pcireg.h
===================================================================
--- sys/dev/bhnd/bhndb/bhndb_pcireg.h
+++ sys/dev/bhnd/bhndb/bhndb_pcireg.h
@@ -29,13 +29,13 @@
*
* = MAJOR CORE REVISIONS =
*
- * There have been four revisions to the BAR0/BAR1 memory mappings used
+ * There have been four revisions to the BAR0 memory mappings used
* in BHND PCI/PCIE bridge cores:
*
* == PCI_V0 ==
* Applies to:
* - PCI (cid=0x804, revision <= 12)
- * BAR size: 8KB
+ * BAR0 size: 8KB
* Address Map:
* [offset+ size] type description
* [0x0000+0x1000] dynamic mapped backplane address space (window 0).
@@ -46,7 +46,7 @@
* Applies to:
* - PCI (cid=0x804, revision >= 13)
* - PCIE (cid=0x820) with ChipCommon (revision <= 31)
- * BAR size: 16KB
+ * BAR0 size: 16KB
* Address Map:
* [offset+ size] type description
* [0x0000+0x1000] dynamic mapped backplane address space (window 0).
@@ -57,7 +57,7 @@
* == PCI_V2 ==
* Applies to:
* - PCIE (cid=0x820) with ChipCommon (revision >= 32)
- * BAR size: 16KB
+ * BAR0 size: 16KB
* Address Map:
* [offset+ size] type description
* [0x0000+0x1000] dynamic mapped backplane address space (window 0).
@@ -68,7 +68,7 @@
* == PCI_V3 ==
* Applies to:
* - PCIE Gen 2 (cid=0x83c)
- * BAR size: 32KB?
+ * BAR0 size: 32KB
* Address Map:
* [offset+ size] type description
* [0x0000+0x1000] dynamic mapped backplane address space (window 0).
@@ -76,6 +76,12 @@
* [0x2000+0x1000] fixed pci/pcie core registers
* [0x3000+0x1000] fixed chipcommon core registers
* [???]
+ * BAR1 size: varies
+ * Address Map:
+ * [offset+ size] type description
+ * [0x0000+0x????] fixed ARM tightly-coupled memory (TCM).
+ * While fullmac chipsets provided a fixed
+ * 4KB mapping, newer devices will vary.
*
* = MINOR CORE REVISIONS =
*
@@ -86,28 +92,6 @@
* == PCI/PCIE Cores Revision >= 14 ==
* - Mapped the clock CSR into the PCI config space. Refer to
* BHND_PCI_CLK_CTL_ST
- *
- * = Hardware Bugs =
- * == BAR1 ==
- *
- * The BHND PCI(e) cores hypothetically support an additional memory mapping
- * of the backplane address space via BAR1, but this appears to be subject
- * to a hardware bug in which BAR1 is initially configured with a 4 byte
- * length.
- *
- * A work-around for this bug may be possible by writing to the PCI core's
- * BAR1 config register (0x4e0), but this requires further research -- I've
- * found three sources for information on the BAR1 PCI core configuration that
- * may be relevant:
- * - The QLogix NetXTreme 10GB PCIe NIC seems to use the same PCIE
- * core IP block as is used in other BHND devices. The bxe(4) driver
- * contains example initialization code and register constants
- * that may apply (e.g. GRC_BAR2_CONFIG/PCI_CONFIG_2_BAR2_SIZE).
- * - The publicly available Broadcom BCM440X data sheet (440X-PG02-R)
- * appears to (partially) document a Broadcom PCI(e) core that has a
- * seemingly compatible programming model.
- * - The Android bcmdhd driver sources include a possible work-around
- * implementation (writing to 0x4e0) in dhd_pcie.c
*/
/* Common PCI/PCIE Config Registers */
@@ -181,12 +165,11 @@
#define BHNDB_PCI_V2_BAR0_CCREGS_OFFSET 0x3000 /* bar0 + 12K accesses chipc core registers */
#define BHNDB_PCI_V2_BAR0_CCREGS_SIZE 0x1000
-/* PCI_V3 */
+/* PCI_V3 (PCIe-G2) */
#define BHNDB_PCI_V3_BAR0_WIN0_CONTROL 0x80 /* backplane address space accessed by BAR0/WIN0 */
-#define BHNDB_PCI_V3_BAR1_WIN0_CONTROL 0x84 /* backplane address space accessed by BAR1/WIN0. */
#define BHNDB_PCI_V3_BAR0_WIN1_CONTROL 0x70 /* backplane address space accessed by BAR0/WIN1 */
-#define BHNDB_PCI_V3_BAR0_SIZE 0x8000 /* 32KB BAR0 (?) */
+#define BHNDB_PCI_V3_BAR0_SIZE 0x8000 /* 32KB BAR0 */
#define BHNDB_PCI_V3_BAR0_WIN0_OFFSET 0x0 /* bar0 + 0x0 accesses configurable 4K region of backplane address space */
#define BHNDB_PCI_V3_BAR0_WIN0_SIZE 0x1000
#define BHNDB_PCI_V3_BAR0_WIN1_OFFSET 0x1000 /* bar0 + 4K accesses second 4K window */
Index: sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
===================================================================
--- sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
+++ sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m
@@ -43,4 +43,23 @@
*/
METHOD bhnd_nvram_src_t nvram_src {
device_t dev;
-}
\ No newline at end of file
+}
+
+/**
+ * Write @p value with @p mask directly to the chipctrl register.
+ *
+ * @param dev A bhnd(4) ChipCommon device.
+ * @param value The value to write.
+ * @param mask The mask of bits to be written from @p value.
+ *
+ * Drivers should only use function for functionality that is not
+ * available via another bhnd_chipc() function.
+ *
+ * Currently, the only known valid use-case is in implementing a hardware
+ * work-around for the BCM4321 PCIe rev7 core revision.
+ */
+METHOD void write_chipctrl {
+ device_t dev;
+ uint32_t value;
+ uint32_t mask;
+}
Index: sys/dev/bhnd/cores/chipc/chipc.c
===================================================================
--- sys/dev/bhnd/cores/chipc/chipc.c
+++ sys/dev/bhnd/cores/chipc/chipc.c
@@ -489,20 +489,38 @@
return (ENODEV);
}
+static void
+chipc_write_chipctrl(device_t dev, uint32_t value, uint32_t mask)
+{
+ struct chipc_softc *sc;
+ uint32_t cctrl;
+
+ sc = device_get_softc(dev);
+
+ CHIPC_LOCK(sc);
+
+ cctrl = bhnd_bus_read_4(sc->core, CHIPC_CHIPCTRL);
+ cctrl = (cctrl & ~mask) | (value | mask);
+ bhnd_bus_write_4(sc->core, CHIPC_CHIPCTRL, cctrl);
+
+ CHIPC_UNLOCK(sc);
+}
+
static device_method_t chipc_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, chipc_probe),
- DEVMETHOD(device_attach, chipc_attach),
- DEVMETHOD(device_detach, chipc_detach),
- DEVMETHOD(device_suspend, chipc_suspend),
- DEVMETHOD(device_resume, chipc_resume),
+ DEVMETHOD(device_probe, chipc_probe),
+ DEVMETHOD(device_attach, chipc_attach),
+ DEVMETHOD(device_detach, chipc_detach),
+ DEVMETHOD(device_suspend, chipc_suspend),
+ DEVMETHOD(device_resume, chipc_resume),
/* ChipCommon interface */
- DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src),
+ DEVMETHOD(bhnd_chipc_nvram_src, chipc_nvram_src),
+ DEVMETHOD(bhnd_chipc_write_chipctrl, chipc_write_chipctrl),
/* NVRAM interface */
- DEVMETHOD(bhnd_nvram_getvar, chipc_nvram_getvar),
- DEVMETHOD(bhnd_nvram_setvar, chipc_nvram_setvar),
+ DEVMETHOD(bhnd_nvram_getvar, chipc_nvram_getvar),
+ DEVMETHOD(bhnd_nvram_setvar, chipc_nvram_setvar),
DEVMETHOD_END
};
Index: sys/dev/bhnd/cores/pci/bhnd_pci.c
===================================================================
--- sys/dev/bhnd/cores/pci/bhnd_pci.c
+++ sys/dev/bhnd/cores/pci/bhnd_pci.c
@@ -429,8 +429,7 @@
int reg)
{
uint32_t cmd;
- uint16_t blk, val;
- uint8_t blk_reg;
+ uint16_t val;
int error;
if (devaddr == MDIO_DEVADDR_NONE)
@@ -438,27 +437,23 @@
/* Extended register access is only supported for the SerDes device,
* using the non-standard C22 extended address mechanism */
- if (!(sc->quirks & BHND_PCI_QUIRK_SD_C22_EXTADDR))
+ if (!(sc->quirks & BHND_PCI_QUIRK_SD_C22_EXTADDR) ||
+ phy != BHND_PCIE_PHYADDR_SD)
+ {
return (~0U);
- if (phy != BHND_PCIE_PHYADDR_SD || devaddr != BHND_PCIE_DEVAD_SD)
- return (~0U);
+ }
/* Enable MDIO access */
BHND_PCI_LOCK(sc);
bhnd_pcie_mdio_enable(sc);
- /* Determine the block and register values */
- blk = (reg & BHND_PCIE_SD_ADDREXT_BLK_MASK);
- blk_reg = (reg & BHND_PCIE_SD_ADDREXT_REG_MASK);
-
/* Write the block address to the address extension register */
- cmd = BHND_PCIE_MDIODATA_ADDR(phy, BHND_PCIE_SD_ADDREXT) |
- (blk & BHND_PCIE_MDIODATA_DATA_MASK);
+ cmd = BHND_PCIE_MDIODATA_ADDR(phy, BHND_PCIE_SD_ADDREXT) | devaddr;
if ((error = bhnd_pcie_mdio_cmd_write(sc, cmd)))
goto cleanup;
/* Issue the read */
- cmd = BHND_PCIE_MDIODATA_ADDR(phy, blk_reg);
+ cmd = BHND_PCIE_MDIODATA_ADDR(phy, reg);
error = bhnd_pcie_mdio_cmd_read(sc, cmd, &val);
cleanup:
@@ -476,8 +471,6 @@
int reg, int val)
{
uint32_t cmd;
- uint16_t blk;
- uint8_t blk_reg;
int error;
if (devaddr == MDIO_DEVADDR_NONE)
@@ -485,27 +478,23 @@
/* Extended register access is only supported for the SerDes device,
* using the non-standard C22 extended address mechanism */
- if (!(sc->quirks & BHND_PCI_QUIRK_SD_C22_EXTADDR))
+ if (!(sc->quirks & BHND_PCI_QUIRK_SD_C22_EXTADDR) ||
+ phy != BHND_PCIE_PHYADDR_SD)
+ {
return (~0U);
- if (phy != BHND_PCIE_PHYADDR_SD || devaddr != BHND_PCIE_DEVAD_SD)
- return (~0U);
+ }
/* Enable MDIO access */
BHND_PCI_LOCK(sc);
bhnd_pcie_mdio_enable(sc);
- /* Determine the block and register values */
- blk = (reg & BHND_PCIE_SD_ADDREXT_BLK_MASK);
- blk_reg = (reg & BHND_PCIE_SD_ADDREXT_REG_MASK);
-
/* Write the block address to the address extension register */
- cmd = BHND_PCIE_MDIODATA_ADDR(phy, BHND_PCIE_SD_ADDREXT) |
- (blk & BHND_PCIE_MDIODATA_DATA_MASK);
+ cmd = BHND_PCIE_MDIODATA_ADDR(phy, BHND_PCIE_SD_ADDREXT) | devaddr;
if ((error = bhnd_pcie_mdio_cmd_write(sc, cmd)))
goto cleanup;
/* Issue the write */
- cmd = BHND_PCIE_MDIODATA_ADDR(phy, blk_reg) |
+ cmd = BHND_PCIE_MDIODATA_ADDR(phy, reg) |
(val & BHND_PCIE_MDIODATA_DATA_MASK);
error = bhnd_pcie_mdio_cmd_write(sc, cmd);
Index: sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c
===================================================================
--- sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c
+++ sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c
@@ -56,28 +56,43 @@
#include <dev/bhnd/bhnd.h>
-#include "bhnd_pcireg.h"
-#include "bhnd_pci_hostbvar.h"
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
-#define BHND_PCI_ASSERT_QUIRK(_sc, _name) \
- KASSERT((_sc)->quirks & (_name), ("quirk " __STRING(_name) " not set"))
+#include <dev/bhnd/cores/chipc/chipc.h>
+#include <dev/bhnd/cores/chipc/chipcreg.h>
-#define BHND_PCI_DEV(_core, _quirks, _chip_quirks) \
- BHND_DEVICE(_core, "", _quirks, _chip_quirks, BHND_DF_HOSTB)
+#include "bhnd_pcireg.h"
+#include "bhnd_pci_hostbvar.h"
static const struct bhnd_device_quirk bhnd_pci_quirks[];
static const struct bhnd_device_quirk bhnd_pcie_quirks[];
+static const struct bhnd_chip_quirk bhnd_pci_chip_quirks[];
static const struct bhnd_chip_quirk bhnd_pcie_chip_quirks[];
+/* Device driver work-around variations */
+typedef enum {
+ BHND_PCI_WAR_ATTACH, /**< apply attach workarounds */
+ BHND_PCI_WAR_RESUME, /**< apply resume workarounds */
+ BHND_PCI_WAR_SUSPEND, /**< apply suspend workarounds */
+ BHND_PCI_WAR_DETACH /**< apply detach workarounds */
+} bhnd_pci_war_state;
+
static int bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc);
-static int bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc);
-static int bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc);
+static int bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc,
+ bhnd_pci_war_state state);
+static int bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc,
+ bhnd_pci_war_state state);
/*
* device/quirk tables
*/
+
+#define BHND_PCI_DEV(_core, _quirks, _chip_quirks) \
+ BHND_DEVICE(_core, "", _quirks, _chip_quirks, BHND_DF_HOSTB)
+
static const struct bhnd_device bhnd_pci_devs[] = {
- BHND_PCI_DEV(PCI, bhnd_pci_quirks, NULL),
+ BHND_PCI_DEV(PCI, bhnd_pci_quirks, bhnd_pci_chip_quirks),
BHND_PCI_DEV(PCIE, bhnd_pcie_quirks, bhnd_pcie_chip_quirks),
BHND_DEVICE_END
};
@@ -89,12 +104,22 @@
BHND_DEVICE_QUIRK_END
};
+static const struct bhnd_chip_quirk bhnd_pci_chip_quirks[] = {
+ /* BCM4321CB2 boards that require 960ns latency timer override */
+ {{ BHND_CHIP_BTYPE(BCM4321CB2) },
+ BHND_PCI_QUIRK_960NS_LATTIM_OVR },
+ {{ BHND_CHIP_BTYPE(BCM4321CB2_AG) },
+ BHND_PCI_QUIRK_960NS_LATTIM_OVR },
+
+ BHND_CHIP_QUIRK_END
+};
+
static const struct bhnd_device_quirk bhnd_pcie_quirks[] = {
{ BHND_HWREV_EQ (0), BHND_PCIE_QUIRK_SDR9_L0s_HANG },
- { BHND_HWREV_RANGE (0, 1), BHND_PCIE_QUIRK_UR_STATUS_FIX },
+ { BHND_HWREV_RANGE (0,1), BHND_PCIE_QUIRK_UR_STATUS_FIX },
{ BHND_HWREV_EQ (1), BHND_PCIE_QUIRK_PCIPM_REQEN },
- { BHND_HWREV_RANGE (3, 5), BHND_PCIE_QUIRK_ASPM_OVR |
+ { BHND_HWREV_RANGE (3,5), BHND_PCIE_QUIRK_ASPM_OVR |
BHND_PCIE_QUIRK_SDR9_POLARITY |
BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY },
@@ -102,37 +127,50 @@
{ BHND_HWREV_GTE (6), BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET },
{ BHND_HWREV_EQ (7), BHND_PCIE_QUIRK_SERDES_NOPLLDOWN },
{ BHND_HWREV_GTE (8), BHND_PCIE_QUIRK_L1_TIMER_PERF },
- { BHND_HWREV_GTE (10), BHND_PCIE_QUIRK_SD_C22_EXTADDR },
+
+ { BHND_HWREV_LTE (17), BHND_PCIE_QUIRK_MAX_MRRS_128 },
+
BHND_DEVICE_QUIRK_END
};
static const struct bhnd_chip_quirk bhnd_pcie_chip_quirks[] = {
/* Apple boards on which BHND_BFL2_PCIEWAR_OVR should be assumed
* to be set. */
- {{ BHND_CHIP_BVENDOR (PCI_VENDOR_APPLE),
- BHND_CHIP_SROMREV (HWREV_EQ(4)),
- BHND_CHIP_BREV (HWREV_LTE(0x71)) },
- BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN },
+ {{ BHND_CHIP_BVENDOR (PCI_VENDOR_APPLE),
+ BHND_CHIP_SROMREV (HWREV_EQ(4)),
+ BHND_CHIP_BREV (HWREV_LTE(0x71)) },
+ BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN },
+
+ /* Apple BCM4322 boards that require 700mV SerDes TX drive strength. */
+ {{ BHND_CHIP_BVT (PCI_VENDOR_APPLE, BCM94322X9) },
+ BHND_PCIE_QUIRK_SERDES_TXDRV_700MV },
+
+ /* Apple BCM4331 board-specific quirks */
+#define BHND_APPLE_4331_QUIRK(_board, ...) \
+ {{ BHND_CHIP_ID (4331), \
+ BHND_CHIP_BVT (PCI_VENDOR_APPLE, _board), }, \
+ __VA_ARGS__ }
+
+ BHND_APPLE_4331_QUIRK(BCM94331X19,
+ BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+
+ BHND_APPLE_4331_QUIRK(BCM94331X28,
+ BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+ BHND_APPLE_4331_QUIRK(BCM94331X28B, BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+
+ BHND_APPLE_4331_QUIRK(BCM94331X29B,
+ BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+
+ BHND_APPLE_4331_QUIRK(BCM94331X19C,
+ BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+
+ BHND_APPLE_4331_QUIRK(BCM94331X29D, BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+ BHND_APPLE_4331_QUIRK(BCM94331X33, BHND_PCIE_QUIRK_DEFAULT_MRRS_512),
+#undef BHND_APPLE_4331_QUIRK
BHND_CHIP_QUIRK_END
};
-// Quirk handling TODO
-// WARs for the following are not yet implemented:
-// - BHND_PCIE_QUIRK_ASPM_OVR
-// - BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN
-// - BHND_PCIE_QUIRK_SERDES_NOPLLDOWN
-// Quirks (and WARs) for the following are not yet defined:
-// - Power savings via MDIO BLK1/PWR_MGMT3 on PCIe hwrev 15-20, 21-22
-// - WOWL PME enable/disable
-// - 4360 PCIe SerDes Tx amplitude/deemphasis (vendor Apple, boards
-// BCM94360X51P2, BCM94360X51A).
-// - PCI latency timer (boards CB2_4321_BOARD, CB2_4321_AG_BOARD)
-// - Max SerDes TX drive strength (vendor Apple, pcie >= rev10,
-// board BCM94322X9)
-// - 700mV SerDes TX drive strength (chipid BCM4331, boards BCM94331X19,
-// BCM94331X28, BCM94331X29B, BCM94331X19C)
-
#define BHND_PCI_SOFTC(_sc) (&((_sc)->common))
#define BHND_PCI_READ_2(_sc, _reg) \
@@ -159,6 +197,13 @@
#define BHND_PCI_MDIO_WRITE(_sc, _phy, _reg, _val) \
bhnd_pcie_mdio_write(BHND_PCI_SOFTC(_sc), (_phy), (_reg), (_val))
+#define BHND_PCI_MDIO_READ_EXT(_sc, _phy, _devaddr, _reg) \
+ bhnd_pcie_mdio_read_ext(BHND_PCI_SOFTC(_sc), (_phy), (_devaddr), (_reg))
+
+#define BHND_PCI_MDIO_WRITE_EXT(_sc, _phy, _devaddr, _reg, _val) \
+ bhnd_pcie_mdio_write_ext(BHND_PCI_SOFTC(_sc), (_phy), \
+ (_devaddr), (_reg), (_val))
+
#define BPCI_REG_SET(_regv, _attr, _val) \
BHND_PCI_REG_SET((_regv), BHND_ ## _attr, (_val))
@@ -180,26 +225,34 @@
int error;
sc = device_get_softc(dev);
+ sc->dev = dev;
sc->quirks = bhnd_device_quirks(dev, bhnd_pci_devs,
sizeof(bhnd_pci_devs[0]));
+ /* Find the host PCI bridge device */
+ sc->pci_dev = bhnd_find_bridge_root(dev, devclass_find("pci"));
+ if (sc->pci_dev == NULL) {
+ device_printf(dev, "parent pci bridge device not found\n");
+ return (ENXIO);
+ }
+
+ /* Common setup */
if ((error = bhnd_pci_generic_attach(dev)))
return (error);
/* Apply early single-shot work-arounds */
- if ((error = bhnd_pci_wars_early_once(sc))) {
- bhnd_pci_generic_detach(dev);
- return (error);
- }
+ if ((error = bhnd_pci_wars_early_once(sc)))
+ goto failed;
/* Apply attach/resume work-arounds */
- if ((error = bhnd_pci_wars_hwup(sc))) {
- bhnd_pci_generic_detach(dev);
- return (error);
- }
-
+ if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_ATTACH)))
+ goto failed;
return (0);
+
+failed:
+ bhnd_pci_generic_detach(dev);
+ return (error);
}
static int
@@ -211,7 +264,7 @@
sc = device_get_softc(dev);
/* Apply suspend/detach work-arounds */
- if ((error = bhnd_pci_wars_hwdown(sc)))
+ if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_DETACH)))
return (error);
return (bhnd_pci_generic_detach(dev));
@@ -226,7 +279,7 @@
sc = device_get_softc(dev);
/* Apply suspend/detach work-arounds */
- if ((error = bhnd_pci_wars_hwdown(sc)))
+ if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_SUSPEND)))
return (error);
return (bhnd_pci_generic_suspend(dev));
@@ -244,7 +297,7 @@
return (error);
/* Apply attach/resume work-arounds */
- if ((error = bhnd_pci_wars_hwup(sc))) {
+ if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_RESUME))) {
bhnd_pci_generic_detach(dev);
return (error);
}
@@ -263,6 +316,36 @@
static int
bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc)
{
+ int error;
+
+ /* Set PCI latency timer */
+ if (sc->quirks & BHND_PCI_QUIRK_960NS_LATTIM_OVR) {
+ pci_write_config(sc->pci_dev, PCIR_LATTIMER, 0x20 /* 960ns */,
+ 1);
+ }
+
+ /* Determine whether ASPM/CLKREQ should be forced on, or forced off. */
+ if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) {
+ struct bhnd_board_info board;
+ bool aspm_en;
+
+ /* Fetch board info */
+ if ((error = bhnd_read_board_info(sc->dev, &board)))
+ return (error);
+
+ /* Check board flags */
+ aspm_en = true;
+ if (board.board_flags2 & BHND_BFL2_PCIEWAR_OVR)
+ aspm_en = false;
+
+ /* Early Apple devices did not (but should have) set
+ * BHND_BFL2_PCIEWAR_OVR in SPROM. */
+ if (sc->quirks & BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN)
+ aspm_en = false;
+
+ sc->aspm_quirk_override.aspm_en = aspm_en;
+ }
+
/* Determine correct polarity by observing the attach-time PCIe PHY
* link status. This is used later to reset/force the SerDes
* polarity */
@@ -270,12 +353,23 @@
uint32_t st;
bool inv;
-
st = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_PLP_STATUSREG);
inv = ((st & BHND_PCIE_PLP_POLARITY_INV) != 0);
sc->sdr9_quirk_polarity.inv = inv;
}
+ /* Override maximum read request size */
+ if (bhnd_get_class(sc->dev) == BHND_DEVCLASS_PCIE) {
+ int msize;
+
+ msize = 128; /* compatible with all PCIe-G1 core revisions */
+ if (sc->quirks & BHND_PCIE_QUIRK_DEFAULT_MRRS_512)
+ msize = 512;
+
+ if (pci_set_max_read_req(sc->pci_dev, msize) == 0)
+ panic("set mrrs on non-PCIe device");
+ }
+
return (0);
}
@@ -284,7 +378,7 @@
* of the bridge device.
*/
static int
-bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc)
+bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state)
{
/* Note that the order here matters; these work-arounds
* should not be re-ordered without careful review of their
@@ -407,6 +501,47 @@
BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt);
}
+ /* Override ASPM/ECPM settings in SPROM shadow and PCIER_LINK_CTL */
+ if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) {
+ bus_size_t reg;
+ uint16_t cfg;
+
+ /* Set ASPM L1/L0s flags in SPROM shadow */
+ reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_ASPM_OFFSET;
+ cfg = BHND_PCI_READ_2(sc, reg);
+
+ if (sc->aspm_quirk_override.aspm_en)
+ cfg |= BHND_PCIE_SRSH_ASPM_ENB;
+ else
+ cfg &= ~BHND_PCIE_SRSH_ASPM_ENB;
+
+ BHND_PCI_WRITE_2(sc, reg, cfg);
+
+
+ /* Set ASPM/ECPM (CLKREQ) flags in PCIe link control register */
+ cfg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2);
+
+ if (sc->aspm_quirk_override.aspm_en)
+ cfg |= PCIEM_LINK_CTL_ASPMC;
+ else
+ cfg &= ~PCIEM_LINK_CTL_ASPMC;
+
+ cfg &= ~PCIEM_LINK_CTL_ECPM; /* CLKREQ# */
+
+ pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, cfg, 2);
+
+ /* Set CLKREQ (ECPM) flags in SPROM shadow */
+ reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_CLKREQ_OFFSET_R5;
+ cfg = BHND_PCI_READ_2(sc, reg);
+
+ if (sc->aspm_quirk_override.aspm_en)
+ cfg |= BHND_PCIE_SRSH_CLKREQ_ENB;
+ else
+ cfg &= ~BHND_PCIE_SRSH_CLKREQ_ENB;
+
+ BHND_PCI_WRITE_2(sc, reg, cfg);
+ }
+
/* Enable L23READY_EXIT_NOPRST if not already set in SPROM. */
if (sc->quirks & BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET) {
bus_size_t reg;
@@ -423,6 +558,54 @@
}
}
+ /* Disable SerDes PLL down */
+ if (sc->quirks & BHND_PCIE_QUIRK_SERDES_NOPLLDOWN) {
+ device_t bhnd, chipc;
+ bus_size_t reg;
+
+ bhnd = device_get_parent(sc->dev);
+ chipc = bhnd_find_child(bhnd, BHND_DEVCLASS_CC, 0);
+ KASSERT(chipc != NULL, ("missing chipcommon device"));
+
+ /* Write SerDes PLL disable flag to the ChipCommon core */
+ BHND_CHIPC_WRITE_CHIPCTRL(chipc, CHIPCTRL_4321_PLL_DOWN,
+ CHIPCTRL_4321_PLL_DOWN);
+
+ /* Clear SPROM shadow backdoor register */
+ reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_BD_OFFSET;
+ BHND_PCI_WRITE_2(sc, reg, 0);
+ }
+
+ /* Adjust TX drive strength and pre-emphasis coefficient */
+ if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST) {
+ uint16_t txdrv;
+
+ /* Fetch current TX driver parameters */
+ txdrv = BHND_PCI_MDIO_READ_EXT(sc, BHND_PCIE_PHYADDR_SD,
+ BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER);
+
+ /* Set 700mV drive strength */
+ if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_700MV) {
+ txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF,
+ BHND_PCIE_APPLE_TX_P2_COEFF_700MV);
+
+ txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER,
+ BHND_PCIE_APPLE_TX_IDRIVER_700MV);
+ }
+
+ /* ... or, set max drive strength */
+ if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_MAX) {
+ txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF,
+ BHND_PCIE_APPLE_TX_P2_COEFF_MAX);
+
+ txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER,
+ BHND_PCIE_APPLE_TX_IDRIVER_MAX);
+ }
+
+ BHND_PCI_MDIO_WRITE_EXT(sc, BHND_PCIE_PHYADDR_SD,
+ BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER, txdrv);
+ }
+
return (0);
}
@@ -431,8 +614,8 @@
* of the bridge device.
*/
static int
-bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc)
-{
+bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state)
+{
/* Reduce L1 timer for better power savings.
* TODO: We could enable/disable this on demand for better power
* savings if we tie this to HT clock request handling */
@@ -443,6 +626,19 @@
BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt);
}
+ /* Enable CLKREQ (ECPM). If suspending, also disable ASPM L1 entry */
+ if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) {
+ uint16_t lcreg;
+
+ lcreg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2);
+
+ lcreg |= PCIEM_LINK_CTL_ECPM; /* CLKREQ# */
+ if (state == BHND_PCI_WAR_SUSPEND)
+ lcreg &= ~PCIEM_LINK_CTL_ASPMC_L1;
+
+ pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, lcreg, 2);
+ }
+
return (0);
}
@@ -456,10 +652,9 @@
DEVMETHOD_END
};
-DEFINE_CLASS_1(bhnd_pci_hostb, bhnd_pci_hostb_driver, bhnd_pci_hostb_methods,
+DEFINE_CLASS_1(bhnd_hostb, bhnd_pci_hostb_driver, bhnd_pci_hostb_methods,
sizeof(struct bhnd_pcihb_softc), bhnd_pci_driver);
-
-DRIVER_MODULE(bhnd_hostb, bhnd, bhnd_pci_hostb_driver, bhnd_hostb_devclass, 0, 0);
+DRIVER_MODULE(bhnd_pci_hostb, bhnd, bhnd_pci_hostb_driver, bhnd_hostb_devclass, 0, 0);
MODULE_VERSION(bhnd_pci_hostb, 1);
MODULE_DEPEND(bhnd_pci_hostb, bhnd, 1, 1, 1);
Index: sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h
===================================================================
--- sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h
+++ sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h
@@ -43,7 +43,7 @@
DECLARE_CLASS(bhnd_pci_hostb_driver);
-/*
+/**
* PCI/PCIe-Gen1 endpoint-mode device quirks
*/
enum {
@@ -56,7 +56,6 @@
*/
BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST = (1<<1),
-
/**
* SBTOPCI_RC_READMULTI must be set on the SSB_PCICORE_SBTOPCI2
* register.
@@ -74,18 +73,24 @@
BHND_PCI_QUIRK_CLKRUN_DSBL = (1<<3),
/**
+ * On PCI-attached BCM4321CB* boards, the PCI latency timer must be set
+ * to 960ns on initial attach.
+ */
+ BHND_PCI_QUIRK_960NS_LATTIM_OVR = (1<<4),
+
+ /**
* TLP workaround for unmatched address handling is required.
*
* This TLP workaround will enable setting of the PCIe UR status bit
* on memory access to an unmatched address.
*/
- BHND_PCIE_QUIRK_UR_STATUS_FIX = (1<<4),
+ BHND_PCIE_QUIRK_UR_STATUS_FIX = (1<<5),
/**
* PCI-PM power management must be explicitly enabled via
* the data link control register.
*/
- BHND_PCIE_QUIRK_PCIPM_REQEN = (1<<5),
+ BHND_PCIE_QUIRK_PCIPM_REQEN = (1<<6),
/**
* Fix L0s to L0 exit transition on SerDes <= rev9 devices.
@@ -98,46 +103,50 @@
* filters must be tweaked to ensure the CDR has fully stabilized
* before asserting receive sequencer completion.
*/
- BHND_PCIE_QUIRK_SDR9_L0s_HANG = (1<<6),
+ BHND_PCIE_QUIRK_SDR9_L0s_HANG = (1<<7),
/**
* The idle time for entering L1 low-power state must be
* explicitly set (to 114ns) to fix slow L1->L0 transition issues.
*/
- BHND_PCIE_QUIRK_L1_IDLE_THRESH = (1<<7),
+ BHND_PCIE_QUIRK_L1_IDLE_THRESH = (1<<8),
/**
* The ASPM L1 entry timer should be extended for better performance,
* and restored for better power savings.
*/
- BHND_PCIE_QUIRK_L1_TIMER_PERF = (1<<8),
+ BHND_PCIE_QUIRK_L1_TIMER_PERF = (1<<9),
/**
* ASPM and ECPM settings must be overridden manually.
+ * Applies to 4311B0/4321B1 chipset revisions.
*
* The override behavior is controlled by the BHND_BFL2_PCIEWAR_OVR
- * flag. If this flag is set, ASPM/CLKREQ should be overridden as
- * enabled; otherwise, they should be overridden as disabled.
+ * flag; if set, ASPM and CLKREQ should be explicitly disabled. If not
+ * set, they should be explicitly enabled.
*
* Attach/Resume:
- * - Set SRSH_ASPM_ENB flag in the SPROM ASPM register.
- * - Set ASPM L0S/L1 in the PCIER_LINK_CTL register.
- * - Set SRSH_CLKREQ_ENB flag in the SPROM CLKREQ_REV5 register.
- * - Clear ECPM in the PCIER_LINK_CTL register.
+ * - Update SRSH_ASPM_ENB flag in the SPROM ASPM register.
+ * - Update SRSH_CLKREQ_ENB flag in the SPROM CLKREQ_REV5
+ * register.
+ * - Update ASPM L0S/L1 flags in PCIER_LINK_CTL register.
+ * - Clear CLKREQ (ECPM) flag in PCIER_LINK_CTL register.
+ *
+ * Suspend:
+ * - Clear ASPM L1 flag in the PCIER_LINK_CTL register.
+ * - Set CLKREQ (ECPM) flag in the PCIER_LINK_CTL register.
*
- * Detach/Suspend:
- * -
- * - When the device enters D3 state, or system enters S3/S4 state,
- * clear ASPM L1 in the PCIER_LINK_CTL register.
+ * Detach:
+ * - Set CLKREQ (ECPM) flag in the PCIER_LINK_CTL register.
*/
- BHND_PCIE_QUIRK_ASPM_OVR = (1<<9),
+ BHND_PCIE_QUIRK_ASPM_OVR = (1<<10),
/**
* A subset of Apple devices did not set the BHND_BFL2_PCIEWAR_OVR
* flag in SPROM; on these devices, the BHND_BFL2_PCIEWAR_OVR flag
* should always be treated as if set.
*/
- BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN = (1<<10),
+ BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN = (1<<11),
/**
* Fix SerDes polarity on SerDes <= rev9 devices.
@@ -145,13 +154,13 @@
* The SerDes polarity must be saved at device attachment, and
* restored on suspend/resume.
*/
- BHND_PCIE_QUIRK_SDR9_POLARITY = (1<<11),
+ BHND_PCIE_QUIRK_SDR9_POLARITY = (1<<12),
/**
* SerDes PLL down flag must be manually disabled (by ChipCommon) on
* resume.
*/
- BHND_PCIE_QUIRK_SERDES_NOPLLDOWN = (1<<12),
+ BHND_PCIE_QUIRK_SERDES_NOPLLDOWN = (1<<13),
/**
* On attach and resume, consult the SPROM to determine whether
@@ -159,31 +168,77 @@
*
* If L23READY_EXIT_NOPRST is not already set in the SPROM, set it
*/
- BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET = (1<<13),
-
- /**
- * The PCIe SerDes supports non-standard extended MDIO register access.
- *
- * The PCIe SerDes supports access to extended MDIO registers via
- * a non-standard Clause 22 address extension mechanism.
- */
- BHND_PCIE_QUIRK_SD_C22_EXTADDR = (1<<14),
+ BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET = (1<<14),
/**
* The PCIe SerDes PLL must be configured to not retry the startup
* sequence upon frequency detection failure on SerDes <= rev9 devices
*
- * The issue this workaround resolves has not be determined.
+ * The issue this workaround resolves is unknown.
*/
BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY = (1<<15),
+
+ /**
+ * Common flag for quirks that require PCIe SerDes TX
+ * drive strength adjustment.
+ *
+ * Only applies to PCIe >= rev10 devices.
+ */
+ BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST = (1<<16),
+
+ /**
+ * On Apple BCM94322X9 devices, the PCIe SerDes TX drive strength
+ * should be set to 700mV.
+ *
+ * The exact issue is unknown, but presumably this workaround
+ * resolves signal integrity issues with these devices.
+ *
+ * Only applies to PCIe >= rev10 devices.
+ */
+ BHND_PCIE_QUIRK_SERDES_TXDRV_700MV = (1<<17) |
+ BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST,
+
+ /**
+ * On some Apple BCM4331-based devices, the PCIe SerDes TX drive
+ * strength should be set to its maximum.
+ *
+ * The exact issue is unknown, but presumably this workaround
+ * resolves signal integrity issues with these devices.
+ */
+ BHND_PCIE_QUIRK_SERDES_TXDRV_MAX = (1<<18) |
+ BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST,
+
+ /**
+ * PCIe cores prior to rev18 do not support an MRRS larger than
+ * 128 bytes.
+ */
+ BHND_PCIE_QUIRK_MAX_MRRS_128 = (1<<19),
+
+ /**
+ * The PCIe core should be configured with an MRRS of 512 bytes.
+ */
+ BHND_PCIE_QUIRK_DEFAULT_MRRS_512 = (1<<20),
};
/**
* bhnd_pci_hostb driver instance state.
*/
struct bhnd_pcihb_softc {
- struct bhnd_pci_softc common; /**< common bhnd_pci state */
- uint32_t quirks; /**< hostb device quirks */
+ struct bhnd_pci_softc common; /**< common bhnd_pci state */
+ device_t dev;
+ device_t pci_dev; /**< host PCI device */
+ uint32_t quirks; /**< hostb device quirks */
+
+ /** BHND_PCIE_QUIRK_ASPM_OVR state. */
+ struct {
+ /**
+ * ASPM/CLKREQ override setting.
+ *
+ * If true, ASPM/CLKREQ should be overridden as enabled.
+ * If false, ASPM/CLKREQ should be overridden as disabled.
+ */
+ bool aspm_en;
+ } aspm_quirk_override;
/** BHND_PCIE_QUIRK_SDR9_POLARITY state. */
struct {
@@ -198,4 +253,4 @@
};
-#endif /* _BHND_CORES_PCI_BHND_PCI_HOSTBVAR_H_ */
\ No newline at end of file
+#endif /* _BHND_CORES_PCI_BHND_PCI_HOSTBVAR_H_ */
Index: sys/dev/bhnd/cores/pci/bhnd_pcib.c
===================================================================
--- sys/dev/bhnd/cores/pci/bhnd_pcib.c
+++ sys/dev/bhnd/cores/pci/bhnd_pcib.c
@@ -86,8 +86,10 @@
DEVMETHOD_END
};
-DEFINE_CLASS_1(bhnd_pcib, bhnd_pcib_driver, bhnd_pcib_methods, sizeof(struct bhnd_pcib_softc), bhnd_pci_driver);
-DRIVER_MODULE(bhnd_pcib, bhnd, bhnd_pcib_driver, bhnd_hostb_devclass, 0, 0);
+DEFINE_CLASS_1(pcib, bhnd_pcib_driver, bhnd_pcib_methods, sizeof(struct bhnd_pcib_softc), bhnd_pci_driver);
+
+static devclass_t pcib_devclass;
+DRIVER_MODULE(bhnd_pcib, bhnd, bhnd_pcib_driver, pcib_devclass, 0, 0);
MODULE_VERSION(bhnd_pcib, 1);
MODULE_DEPEND(bhnd_pcib, bhnd, 1, 1, 1);
Index: sys/dev/bhnd/cores/pci/bhnd_pcireg.h
===================================================================
--- sys/dev/bhnd/cores/pci/bhnd_pcireg.h
+++ sys/dev/bhnd/cores/pci/bhnd_pcireg.h
@@ -321,12 +321,8 @@
* PCIe-G1 SerDes MDIO Registers (>= rev10)
*/
#define BHND_PCIE_PHYADDR_SD 0x0 /* serdes PHY address */
-#define BHND_PCIE_DEVAD_SD 0x1 /* serdes pseudo-devad (PMA) recognized by
- the bhnd_mdio_pcie driver */
#define BHND_PCIE_SD_ADDREXT 0x1F /* serdes address extension register */
-#define BHND_PCIE_SD_ADDREXT_BLK_MASK 0xFFF0 /* register block mask */
-#define BHND_PCIE_SD_ADDREXT_REG_MASK 0x000F /* register address mask */
#define BHND_PCIE_SD_REGS_IEEE0 0x0000 /* IEEE0 AN CTRL block */
#define BHND_PCIE_SD_REGS_IEEE1 0x0010 /* IEEE1 AN ADV block */
@@ -335,10 +331,30 @@
#define BHND_PCIE_SD_REGS_BLK2 0x8020 /* ??? */
#define BHND_PCIE_SD_REGS_BLK3 0x8030 /* ??? */
#define BHND_PCIE_SD_REGS_BLK4 0x8040 /* ??? */
-#define BHND_PCIE_SD_REGS_TXPLL 0x8080 /* TXPLL register block */
-#define BHND_PCIE_SD_REGS_TXCTRL0 0x8200 /* ??? */
-#define BHND_PCIE_SD_REGS_SERDESID 0x8310 /* ??? */
-#define BHND_PCIE_SD_REGS_RXCTRL0 0x8400 /* ??? */
+#define BHND_PCIE_SD_REGS_PLL 0x8080 /* (?) PLL register block */
+#define BHND_PCIE_SD_REGS_TX0 0x8200 /* (?) Transmit 0 block */
+#define BHND_PCIE_SD_REGS_SERDESID 0x8310 /* ??? */
+#define BHND_PCIE_SD_REGS_RX0 0x8400 /* (?) Receive 0 register block */
+
+/* The interpretation of these registers and values are just guesses based on
+ * the limited available documentation from other (likely similar) Broadcom
+ * SerDes IP. */
+#define BHND_PCIE_SD_TX_DRIVER 0x17 /* TX transmit driver register */
+#define BHND_PCIE_SD_TX_DRIVER_IFIR_MASK 0x000E /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_IFIR_SHIFT 1 /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_IPRE_MASK 0x00F0 /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_IPRE_SHIFT 4 /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_IDRIVER_MASK 0x0F00 /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_IDRIVER_SHIFT 8 /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_P2_COEFF_SHIFT 12 /* unconfirmed */
+#define BHND_PCIE_SD_TX_DRIVER_P2_COEFF_MASK 0xF000 /* unconfirmed */
+
+/* Constants used with host bridge quirk handling */
+#define BHND_PCIE_APPLE_TX_P2_COEFF_MAX 0x7 /* 9.6dB pre-emphassis coeff (???) */
+#define BHND_PCIE_APPLE_TX_IDRIVER_MAX 0xF /* 1400mV voltage range (???) */
+
+#define BHND_PCIE_APPLE_TX_P2_COEFF_700MV 0x7 /* 2.3dB pre-emphassis coeff (???) */
+#define BHND_PCIE_APPLE_TX_IDRIVER_700MV 0x0 /* 670mV voltage range (???) */
/*
* PCIe-G1 SerDes-R9 MDIO Registers (<= rev9)
@@ -389,23 +405,12 @@
#define BHND_PCIE_SRSH_ASPM_L0s_ENB 0x8 /* bit 3 */
#define BHND_PCIE_SRSH_PCIE_MISC_CONFIG 10 /* word 5 */
#define BHND_PCIE_SRSH_L23READY_EXIT_NOPRST 0x8000 /* bit 15 */
-#define BHND_PCIE_SRSH_CLKREQ_OFFSET_REV5 40 /* word 20 for srom rev <= 5 */
-#define BHND_PCIE_SRSH_CLKREQ_OFFSET_REV8 104 /* word 52 for srom rev 8 */
+#define BHND_PCIE_SRSH_CLKREQ_OFFSET_R5 40 /* word 20 for srom rev <= 5 */
+#define BHND_PCIE_SRSH_CLKREQ_OFFSET_R8 104 /* word 52 for srom rev 8 */
#define BHND_PCIE_SRSH_CLKREQ_ENB 0x0800 /* bit 11 */
#define BHND_PCIE_SRSH_BD_OFFSET 12 /* word 6 */
#define BHND_PCIE_SRSH_AUTOINIT_OFFSET 36 /* auto initialization enable */
-/* Linkcontrol reg offset in PCIE Cap */
-#define BHND_PCIE_CAP_LINKCTRL_OFFSET 16 /* linkctrl offset in pcie cap */
-#define BHND_PCIE_CAP_LCREG_ASPML0s 0x01 /* ASPM L0s in linkctrl */
-#define BHND_PCIE_CAP_LCREG_ASPML1 0x02 /* ASPM L1 in linkctrl */
-#define BHND_PCIE_CLKREQ_ENAB 0x100 /* CLKREQ Enab in linkctrl */
-
-#define BHND_PCIE_ASPM_ENAB 3 /* ASPM L0s & L1 in linkctrl */
-#define BHND_PCIE_ASPM_L1_ENAB 2 /* ASPM L0s & L1 in linkctrl */
-#define BHND_PCIE_ASPM_L0s_ENAB 1 /* ASPM L0s & L1 in linkctrl */
-#define BHND_PCIE_ASPM_DISAB 0 /* ASPM L0s & L1 in linkctrl */
-
/* Status reg PCIE_PLP_STATUSREG */
#define BHND_PCIE_PLP_POLARITY_INV 0x10 /* lane polarity is inverted */
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2.c
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2.c
@@ -0,0 +1,289 @@
+/*-
+ * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Broadcom Common PCIe-G2 Support.
+ *
+ * This base driver implementation is shared by the bhnd_pcib_g2 (root complex)
+ * and bhnd_pci_hostb_g2 (host bridge) drivers.
+ */
+
+#include <sys/param.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/bhnd/bhnd.h>
+#include <dev/mdio/mdio.h>
+
+#include "bhnd_pcie2_reg.h"
+#include "bhnd_pcie2_var.h"
+
+static struct bhnd_device_quirk bhnd_pcie2_quirks[];
+
+#define BHND_PCIE_DEV(_core, _desc, ...) \
+ BHND_DEVICE(_core, _desc, bhnd_pcie2_quirks, NULL, ## __VA_ARGS__)
+
+static const struct bhnd_device bhnd_pcie2_devs[] = {
+ BHND_PCIE_DEV(PCIE2, "PCIe-G2 Host-PCI bridge", BHND_DF_HOSTB),
+ BHND_PCIE_DEV(PCIE2, "PCIe-G2 PCI-BHND bridge"),
+
+ BHND_DEVICE_END
+};
+
+/* Device quirks tables */
+static struct bhnd_device_quirk bhnd_pcie2_quirks[] = {
+ BHND_DEVICE_QUIRK_END
+};
+
+int
+bhnd_pcie2_generic_probe(device_t dev)
+{
+ const struct bhnd_device *id;
+
+ id = bhnd_device_lookup(dev, bhnd_pcie2_devs,
+ sizeof(bhnd_pcie2_devs[0]));
+ if (id == NULL)
+ return (ENXIO);
+
+ bhnd_set_custom_core_desc(dev, id->desc);
+ return (BUS_PROBE_DEFAULT);
+}
+
+int
+bhnd_pcie2_generic_attach(device_t dev)
+{
+ struct bhnd_pcie2_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->quirks = bhnd_device_quirks(dev, bhnd_pcie2_devs,
+ sizeof(bhnd_pcie2_devs[0]));
+
+ /* Allocate bus resources */
+ sc->mem_res = bhnd_alloc_resource_any(dev, SYS_RES_MEMORY, &sc->mem_rid,
+ RF_ACTIVE);
+ if (sc->mem_res == NULL)
+ return (ENXIO);
+
+ BHND_PCIE2_LOCK_INIT(sc);
+
+ /* Probe and attach children */
+ if ((error = bus_generic_attach(dev)))
+ goto cleanup;
+
+ return (0);
+
+cleanup:
+ bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
+ BHND_PCIE2_LOCK_DESTROY(sc);
+
+ return (error);
+}
+
+int
+bhnd_pcie2_generic_detach(device_t dev)
+{
+ struct bhnd_pcie2_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if ((error = bus_generic_detach(dev)))
+ return (error);
+
+ bhnd_release_resource(dev, SYS_RES_MEMORY, sc->mem_rid, sc->mem_res);
+
+ BHND_PCIE2_LOCK_DESTROY(sc);
+
+ return (0);
+}
+
+static struct resource_list *
+bhnd_pcie2_get_resource_list(device_t dev, device_t child)
+{
+ struct bhnd_pcie2_devinfo *dinfo;
+
+ if (device_get_parent(child) != dev)
+ return (NULL);
+
+ dinfo = device_get_ivars(child);
+ return (&dinfo->resources);
+}
+
+static device_t
+bhnd_pcie2_add_child(device_t dev, u_int order, const char *name, int unit)
+{
+ struct bhnd_pcie2_devinfo *dinfo;
+ device_t child;
+
+ child = device_add_child_ordered(dev, order, name, unit);
+ if (child == NULL)
+ return (NULL);
+
+ dinfo = malloc(sizeof(struct bhnd_pcie2_devinfo), M_DEVBUF, M_NOWAIT);
+ if (dinfo == NULL) {
+ device_delete_child(dev, child);
+ return (NULL);
+ }
+
+ resource_list_init(&dinfo->resources);
+
+ device_set_ivars(child, dinfo);
+ return (child);
+}
+
+static void
+bhnd_pcie2_child_deleted(device_t dev, device_t child)
+{
+ struct bhnd_pcie2_devinfo *dinfo;
+
+ if (device_get_parent(child) != dev)
+ return;
+
+ dinfo = device_get_ivars(child);
+ if (dinfo != NULL) {
+ resource_list_free(&dinfo->resources);
+ free(dinfo, M_DEVBUF);
+ }
+
+ device_set_ivars(child, NULL);
+}
+
+int
+bhnd_pcie2_generic_suspend(device_t dev)
+{
+ return (bus_generic_suspend(dev));
+}
+
+int
+bhnd_pcie2_generic_resume(device_t dev)
+{
+ return (bus_generic_resume(dev));
+}
+
+/**
+ * Read a 32-bit PCIe TLP/DLLP/PLP protocol register.
+ *
+ * @param sc The bhndb_pci driver state.
+ * @param addr The protocol register offset.
+ */
+uint32_t
+bhnd_pcie2_read_proto_reg(struct bhnd_pcie2_softc *sc, uint32_t addr)
+{
+ // TODO
+ return (ENXIO);
+}
+
+/**
+ * Write a 32-bit PCIe TLP/DLLP/PLP protocol register value.
+ *
+ * @param sc The bhndb_pci driver state.
+ * @param addr The protocol register offset.
+ * @param val The value to write to @p addr.
+ */
+void
+bhnd_pcie2_write_proto_reg(struct bhnd_pcie2_softc *sc, uint32_t addr,
+ uint32_t val)
+{
+ // TODO
+ panic("unimplemented");
+}
+
+int
+bhnd_pcie2_mdio_read(struct bhnd_pcie2_softc *sc, int phy, int reg)
+{
+ // TODO
+ return (ENXIO);
+}
+
+int
+bhnd_pcie2_mdio_write(struct bhnd_pcie2_softc *sc, int phy, int reg, int val)
+{
+ // TODO
+ return (ENXIO);
+}
+
+int
+bhnd_pcie2_mdio_read_ext(struct bhnd_pcie2_softc *sc, int phy, int devaddr,
+ int reg)
+{
+ // TODO
+ return (ENXIO);
+}
+
+int
+bhnd_pcie2_mdio_write_ext(struct bhnd_pcie2_softc *sc, int phy, int devaddr,
+ int reg, int val)
+{
+ // TODO
+ return (ENXIO);
+}
+
+static device_method_t bhnd_pcie2_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, bhnd_pcie2_generic_probe),
+ DEVMETHOD(device_attach, bhnd_pcie2_generic_attach),
+ DEVMETHOD(device_detach, bhnd_pcie2_generic_detach),
+ DEVMETHOD(device_suspend, bhnd_pcie2_generic_suspend),
+ DEVMETHOD(device_resume, bhnd_pcie2_generic_resume),
+
+ /* Bus interface */
+ DEVMETHOD(bus_add_child, bhnd_pcie2_add_child),
+ DEVMETHOD(bus_child_deleted, bhnd_pcie2_child_deleted),
+ DEVMETHOD(bus_print_child, bus_generic_print_child),
+ DEVMETHOD(bus_get_resource_list, bhnd_pcie2_get_resource_list),
+ DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
+ DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
+ DEVMETHOD(bus_delete_resource, bus_generic_rl_delete_resource),
+
+ DEVMETHOD(bus_alloc_resource, bus_generic_rl_alloc_resource),
+ DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
+ DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
+ DEVMETHOD(bus_adjust_resource, bus_generic_adjust_resource),
+ DEVMETHOD(bus_release_resource, bus_generic_rl_release_resource),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_0(bhnd_pcie2, bhnd_pcie2_driver, bhnd_pcie2_methods,
+ sizeof(struct bhnd_pcie2_softc));
+MODULE_DEPEND(bhnd_pcie2, bhnd, 1, 1, 1);
+MODULE_DEPEND(bhnd_pcie2, pci, 1, 1, 1);
+MODULE_VERSION(bhnd_pcie2, 1);
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c
@@ -0,0 +1,254 @@
+/*-
+ * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Broadcom BHND PCIe-Gen2 PCI-Host Bridge.
+ *
+ * This driver handles all interactions with PCIe-G2 bridge cores operating in
+ * endpoint mode.
+ *
+ * Host-level PCI operations are handled at the bhndb bridge level by the
+ * bhndb_pci driver.
+ */
+
+// TODO
+//
+// A full survey of known quirks/work-arounds has not been completed.
+//
+// Work-arounds for the following are not yet implemented:
+// - BHND_PCIE2_QUIRK_SERDES_TXDRV_DEEMPH
+// 4360 PCIe SerDes Tx amplitude/deemphasis (vendor Apple, boards
+// BCM94360X51P2, BCM94360X51A)
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+
+#include <sys/malloc.h>
+
+#include <sys/bus.h>
+#include <sys/module.h>
+
+#include <sys/systm.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/bhnd/bhnd.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include "bhnd_pcie2_reg.h"
+#include "bhnd_pcie2_hostbvar.h"
+
+static const struct bhnd_device_quirk bhnd_pcie2_quirks[];
+static const struct bhnd_chip_quirk bhnd_pcie2_chip_quirks[];
+
+
+static int bhnd_pcie2_wars_early_once(struct bhnd_pcie2hb_softc *sc);
+static int bhnd_pcie2_wars_hwup(struct bhnd_pcie2hb_softc *sc);
+static int bhnd_pcie2_wars_hwdown(struct bhnd_pcie2hb_softc *sc);
+
+/*
+ * device/quirk tables
+ */
+
+#define BHND_PCI_DEV(_core, _quirks, _chip_quirks) \
+ BHND_DEVICE(_core, "", _quirks, _chip_quirks, BHND_DF_HOSTB)
+
+static const struct bhnd_device bhnd_pcie2_devs[] = {
+ BHND_PCI_DEV(PCIE2, bhnd_pcie2_quirks, bhnd_pcie2_chip_quirks),
+ BHND_DEVICE_END
+};
+
+static const struct bhnd_device_quirk bhnd_pcie2_quirks[] = {
+ BHND_DEVICE_QUIRK_END
+};
+
+static const struct bhnd_chip_quirk bhnd_pcie2_chip_quirks[] = {
+ /* Apple BCM4360 boards that require adjusting TX amplitude and
+ * differential output de-emphasis of the PCIe SerDes */
+ {{ BHND_CHIP_BVT (PCI_VENDOR_APPLE, BCM94360X51P2) },
+ BHND_PCIE2_QUIRK_SERDES_TXDRV_DEEMPH },
+ {{ BHND_CHIP_BVT (PCI_VENDOR_APPLE, BCM94360X51A) },
+ BHND_PCIE2_QUIRK_SERDES_TXDRV_DEEMPH },
+
+ BHND_CHIP_QUIRK_END
+};
+
+static int
+bhnd_pcie2_hostb_attach(device_t dev)
+{
+ struct bhnd_pcie2hb_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
+ sc->quirks = bhnd_device_quirks(dev, bhnd_pcie2_devs,
+ sizeof(bhnd_pcie2_devs[0]));
+
+ /* Find the host PCI bridge device */
+ sc->pci_dev = bhnd_find_bridge_root(dev, devclass_find("pci"));
+ if (sc->pci_dev == NULL) {
+ device_printf(dev, "parent pci bridge device not found\n");
+ return (ENXIO);
+ }
+
+ /* Common setup */
+ if ((error = bhnd_pcie2_generic_attach(dev)))
+ return (error);
+
+
+ /* Apply early single-shot work-arounds */
+ if ((error = bhnd_pcie2_wars_early_once(sc)))
+ goto failed;
+
+
+ /* Apply attach/resume work-arounds */
+ if ((error = bhnd_pcie2_wars_hwup(sc)))
+ goto failed;
+
+
+ return (0);
+
+failed:
+ bhnd_pcie2_generic_detach(dev);
+ return (error);
+}
+
+static int
+bhnd_pcie2_hostb_detach(device_t dev)
+{
+ struct bhnd_pcie2hb_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ /* Apply suspend/detach work-arounds */
+ if ((error = bhnd_pcie2_wars_hwdown(sc)))
+ return (error);
+
+ return (bhnd_pcie2_generic_detach(dev));
+}
+
+static int
+bhnd_pcie2_hostb_suspend(device_t dev)
+{
+ struct bhnd_pcie2hb_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ /* Apply suspend/detach work-arounds */
+ if ((error = bhnd_pcie2_wars_hwdown(sc)))
+ return (error);
+
+ return (bhnd_pcie2_generic_suspend(dev));
+}
+
+static int
+bhnd_pcie2_hostb_resume(device_t dev)
+{
+ struct bhnd_pcie2hb_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ if ((error = bhnd_pcie2_generic_resume(dev)))
+ return (error);
+
+ /* Apply attach/resume work-arounds */
+ if ((error = bhnd_pcie2_wars_hwup(sc))) {
+ bhnd_pcie2_generic_detach(dev);
+ return (error);
+ }
+
+ return (0);
+}
+
+/**
+ * Apply any hardware work-arounds that must be executed exactly once, early in
+ * the attach process.
+ *
+ * This must be called after core enumeration and discovery of all applicable
+ * quirks, but prior to probe/attach of any cores, parsing of
+ * SPROM, etc.
+ */
+static int
+bhnd_pcie2_wars_early_once(struct bhnd_pcie2hb_softc *sc)
+{
+ // TODO
+ return (ENXIO);
+}
+
+/**
+ * Apply any hardware workarounds that are required upon attach or resume
+ * of the bridge device.
+ */
+static int
+bhnd_pcie2_wars_hwup(struct bhnd_pcie2hb_softc *sc)
+{
+ // TODO
+ return (ENXIO);
+}
+
+/**
+ * Apply any hardware workarounds that are required upon detach or suspend
+ * of the bridge device.
+ */
+static int
+bhnd_pcie2_wars_hwdown(struct bhnd_pcie2hb_softc *sc)
+{
+ // TODO
+ return (ENXIO);
+}
+
+static device_method_t bhnd_pcie2_hostb_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_attach, bhnd_pcie2_hostb_attach),
+ DEVMETHOD(device_detach, bhnd_pcie2_hostb_detach),
+ DEVMETHOD(device_suspend, bhnd_pcie2_hostb_suspend),
+ DEVMETHOD(device_resume, bhnd_pcie2_hostb_resume),
+
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(bhnd_hostb, bhnd_pcie2_hostb_driver,
+ bhnd_pcie2_hostb_methods, sizeof(struct bhnd_pcie2hb_softc),
+ bhnd_pcie2_driver);
+
+DRIVER_MODULE(bhnd_pcie2_hostb, bhnd, bhnd_pcie2_hostb_driver, bhnd_hostb_devclass, 0, 0);
+
+MODULE_VERSION(bhnd_pcie2_hostb, 1);
+MODULE_DEPEND(bhnd_pcie2_hostb, bhnd, 1, 1, 1);
+MODULE_DEPEND(bhnd_pcie2_hostb, bhnd_pcie2, 1, 1, 1);
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostbvar.h
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostbvar.h
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BHND_CORES_PCIE2_BHND_PCI_HOSTBVAR_H_
+#define _BHND_CORES_PCIE2_BHND_PCI_HOSTBVAR_H_
+
+/*
+ * PCIe-Gen2 Host Bridge definitions.
+ */
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+#include "bhnd_pcie2_var.h"
+
+DECLARE_CLASS(bhnd_pcie2_hostb_driver);
+
+
+/*
+ * PCIe-Gen2 endpoint-mode device quirks
+ */
+enum {
+ /**
+ * The PCIe SerDes output should be configured with an amplitude of
+ * 1214mVpp and a differential output de-emphasis of -8.46dB.
+ *
+ * The exact issue this workaround resolves is unknown.
+ */
+ BHND_PCIE2_QUIRK_SERDES_TXDRV_DEEMPH = (1<<0),
+};
+
+
+/**
+ * bhnd_pci_hostb driver instance state.
+ */
+struct bhnd_pcie2hb_softc {
+ struct bhnd_pcie2_softc common; /**< common bhnd_pcie2 state */
+ device_t dev;
+ device_t pci_dev; /**< host PCI device */
+ uint32_t quirks; /**< hostb device quirks */
+};
+
+
+#endif /* _BHND_CORES_PCIE2_BHND_PCI_HOSTBVAR_H_ */
\ No newline at end of file
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h
@@ -0,0 +1,228 @@
+/*-
+ * Copyright (c) 2016 Landon Fuller <landon@landonf.org>
+ * Copyright (c) 2015 Broadcom Corporation
+ * All rights reserved.
+ *
+ * This file is derived from the pcie_core.h and pcie2_core.h headers
+ * from Broadcom's Linux driver sources as distributed by dd-wrt.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BHND_CORES_PCIE2_BHND_PCIE2_REG_H_
+#define _BHND_CORES_PCIE2_BHND_PCIE2_REG_H_
+
+#define BHND_PCIE2_CLK_CONTROL 0x000
+
+#define BHND_PCIE2_RC_PM_CONTROL 0x004
+#define BHND_PCIE2_RC_PM_STATUS 0x008
+#define BHND_PCIE2_EP_PM_CONTROL 0x00C
+#define BHND_PCIE2_EP_PM_STATUS 0x010
+#define BHND_PCIE2_EP_LTR_CONTROL 0x014
+#define BHND_PCIE2_EP_LTR_STATUS 0x018
+#define BHND_PCIE2_EP_OBFF_STATUS 0x01C
+#define BHND_PCIE2_PCIE_ERR_STATUS 0x020
+#define BHND_PCIE2_RC_AXI_CONFIG 0x100
+#define BHND_PCIE2_EP_AXI_CONFIG 0x104
+#define BHND_PCIE2_RXDEBUG_STATUS0 0x108
+#define BHND_PCIE2_RXDEBUG_CONTROL0 0x10C
+
+#define BHND_PCIE2_CONFIGINDADDR 0x120
+#define BHND_PCIE2_CONFIGINDDATA 0x124
+
+#define BHND_PCIE2_CFG_ADDR 0x1F8
+#define BHND_PCIE2_CFG_DATA 0x1FC
+
+#define BHND_PCIE2_SYS_EQ_PAGE 0x200
+#define BHND_PCIE2_SYS_MSI_PAGE 0x204
+#define BHND_PCIE2_SYS_MSI_INTREN 0x208
+#define BHND_PCIE2_SYS_MSI_CTRL0 0x210
+#define BHND_PCIE2_SYS_MSI_CTRL1 0x214
+#define BHND_PCIE2_SYS_MSI_CTRL2 0x218
+#define BHND_PCIE2_SYS_MSI_CTRL3 0x21C
+#define BHND_PCIE2_SYS_MSI_CTRL4 0x220
+#define BHND_PCIE2_SYS_MSI_CTRL5 0x224
+
+#define BHND_PCIE2_SYS_EQ_HEAD0 0x250
+#define BHND_PCIE2_SYS_EQ_TAIL0 0x254
+#define BHND_PCIE2_SYS_EQ_HEAD1 0x258
+#define BHND_PCIE2_SYS_EQ_TAIL1 0x25C
+#define BHND_PCIE2_SYS_EQ_HEAD2 0x260
+#define BHND_PCIE2_SYS_EQ_TAIL2 0x264
+#define BHND_PCIE2_SYS_EQ_HEAD3 0x268
+#define BHND_PCIE2_SYS_EQ_TAIL3 0x26C
+#define BHND_PCIE2_SYS_EQ_HEAD4 0x270
+#define BHND_PCIE2_SYS_EQ_TAIL4 0x274
+#define BHND_PCIE2_SYS_EQ_HEAD5 0x278
+#define BHND_PCIE2_SYS_EQ_TAIL5 0x27C
+
+#define BHND_PCIE2_SYS_RC_INTX_EN 0x330
+#define BHND_PCIE2_SYS_RC_INTX_CSR 0x334
+#define BHND_PCIE2_SYS_MSI_REQ 0x340
+#define BHND_PCIE2_SYS_HOST_INTR_EN 0x344
+#define BHND_PCIE2_SYS_HOST_INTR_CSR 0x348
+#define BHND_PCIE2_SYS_HOST_INTR0 0x350
+#define BHND_PCIE2_SYS_HOST_INTR1 0x354
+#define BHND_PCIE2_SYS_HOST_INTR2 0x358
+#define BHND_PCIE2_SYS_HOST_INTR3 0x35C
+#define BHND_PCIE2_SYS_EP_INT_EN0 0x360
+#define BHND_PCIE2_SYS_EP_INT_EN1 0x364
+#define BHND_PCIE2_SYS_EP_INT_CSR0 0x370
+#define BHND_PCIE2_SYS_EP_INT_CSR1 0x374
+
+#define BHND_PCIE2_MDIO_CTL 0x128 /**< mdio control */
+#define BHND_PCIE2_MDIO_WRDATA 0x12C /**< mdio data write */
+#define BHND_PCIE2_MDIO_RDDATA 0x130 /**< mdio data read */
+
+
+/* DMA doorbell registers (>= rev5) */
+#define BHND_PCIE2_DB0_HOST2DEV0 0x140
+#define BHND_PCIE2_DB0_HOST2DEV1 0x144
+#define BHND_PCIE2_DB0_DEV2HOST0 0x148
+#define BHND_PCIE2_DB0_DEV2HOST1 0x14C
+
+#define BHND_PCIE2_DB1_HOST2DEV0 0x150
+#define BHND_PCIE2_DB1_HOST2DEV1 0x154
+#define BHND_PCIE2_DB1_DEV2HOST0 0x158
+#define BHND_PCIE2_DB1_DEV2HOST1 0x15C
+
+#define BHND_PCIE2_DB2_HOST2DEV0 0x160
+#define BHND_PCIE2_DB2_HOST2DEV1 0x164
+#define BHND_PCIE2_DB2_DEV2HOST0 0x168
+#define BHND_PCIE2_DB2_DEV2HOST1 0x16C
+
+#define BHND_PCIE2_DB3_HOST2DEV0 0x170
+#define BHND_PCIE2_DB3_HOST2DEV1 0x174
+#define BHND_PCIE2_DB3_DEV2HOST0 0x178
+#define BHND_PCIE2_DB3_DEV2HOST1 0x17C
+
+#define BHND_PCIE2_DATAINTF 0x180
+#define BHND_PCIE2_INTRLAZY0_DEV2HOST 0x188
+#define BHND_PCIE2_INTRLAZY0_HOST2DEV 0x18c
+#define BHND_PCIE2_INTSTAT0_HOST2DEV 0x190
+#define BHND_PCIE2_INTMASK0_HOST2DEV 0x194
+#define BHND_PCIE2_INTSTAT0_DEV2HOST 0x198
+#define BHND_PCIE2_INTMASK0_DEV2HOST 0x19c
+#define BHND_PCIE2_LTR_STATE 0x1A0
+#define BHND_PCIE2_PWR_INT_STATUS 0x1A4
+#define BHND_PCIE2_PWR_INT_MASK 0x1A8
+
+/* DMA channel registers */
+#define BHND_PCIE2_DMA0_HOST2DEV_TX 0x200
+#define BHND_PCIE2_DMA0_HOST2DEV_RX 0x220
+#define BHND_PCIE2_DMA0_DEV2HOST_TX 0x240
+#define BHND_PCIE2_DMA0_DEV2HOST_RX 0x260
+
+#define BHND_PCIE2_DMA1_HOST2DEV_TX 0x280
+#define BHND_PCIE2_DMA1_HOST2DEV_RX 0x2A0
+#define BHND_PCIE2_DMA1_DEV2HOST_TX 0x2C0
+#define BHND_PCIE2_DMA1_DEV2HOST_RX 0x2E0
+
+#define BHND_PCIE2_DMA2_HOST2DEV_TX 0x300
+#define BHND_PCIE2_DMA2_HOST2DEV_RX 0x320
+#define BHND_PCIE2_DMA2_DEV2HOST_TX 0x340
+#define BHND_PCIE2_DMA2_DEV2HOST_RX 0x360
+
+#define BHND_PCIE2_DMA3_HOST2DEV_TX 0x380
+#define BHND_PCIE2_DMA3_HOST2DEV_RX 0x3A0
+#define BHND_PCIE2_DMA3_DEV2HOST_TX 0x3C0
+#define BHND_PCIE2_DMA3_DEV2HOST_RX 0x3E0
+
+#define BHND_PCIE2_PCIE_FUNC0_CFG 0x400 /**< PCIe function 0 config space */
+#define BHND_PCIE2_PCIE_FUNC1_CFG 0x500 /**< PCIe function 1 config space */
+#define BHND_PCIE2_PCIE_FUNC2_CFG 0x600 /**< PCIe function 2 config space */
+#define BHND_PCIE2_PCIE_FUNC3_CFG 0x700 /**< PCIe function 3 config space */
+#define BHND_PCIE2_SPROM 0x800 /**< SPROM shadow */
+
+#define BHND_PCIE2_FUNC0_IMAP0_0 0xC00
+#define BHND_PCIE2_FUNC0_IMAP0_1 0xC04
+#define BHND_PCIE2_FUNC0_IMAP0_2 0xC08
+#define BHND_PCIE2_FUNC0_IMAP0_3 0xC0C
+#define BHND_PCIE2_FUNC0_IMAP0_4 0xC10
+#define BHND_PCIE2_FUNC0_IMAP0_5 0xC14
+#define BHND_PCIE2_FUNC0_IMAP0_6 0xC18
+#define BHND_PCIE2_FUNC0_IMAP0_7 0xC1C
+
+#define BHND_PCIE2_FUNC1_IMAP0_0 0xC20
+#define BHND_PCIE2_FUNC1_IMAP0_1 0xC24
+#define BHND_PCIE2_FUNC1_IMAP0_2 0xC28
+#define BHND_PCIE2_FUNC1_IMAP0_3 0xC2C
+#define BHND_PCIE2_FUNC1_IMAP0_4 0xC30
+#define BHND_PCIE2_FUNC1_IMAP0_5 0xC34
+#define BHND_PCIE2_FUNC1_IMAP0_6 0xC38
+#define BHND_PCIE2_FUNC1_IMAP0_7 0xC3C
+
+#define BHND_PCIE2_FUNC0_IMAP1 0xC80
+#define BHND_PCIE2_FUNC1_IMAP1 0xC88
+#define BHND_PCIE2_FUNC0_IMAP2 0xCC0
+#define BHND_PCIE2_FUNC1_IMAP2 0xCC8
+
+#define BHND_PCIE2_IARR0_LOWER 0xD00
+#define BHND_PCIE2_IARR0_UPPER 0xD04
+#define BHND_PCIE2_IARR1_LOWER 0xD08
+#define BHND_PCIE2_IARR1_UPPER 0xD0C
+#define BHND_PCIE2_IARR2_LOWER 0xD10
+#define BHND_PCIE2_IARR2_UPPER 0xD14
+#define BHND_PCIE2_OARR0 0xD20
+#define BHND_PCIE2_OARR1 0xD28
+#define BHND_PCIE2_OARR2 0xD30
+#define BHND_PCIE2_OMAP0_LOWER 0xD40
+#define BHND_PCIE2_OMAP0_UPPER 0xD44
+#define BHND_PCIE2_OMAP1_LOWER 0xD48
+#define BHND_PCIE2_OMAP1_UPPER 0xD4C
+#define BHND_PCIE2_OMAP2_LOWER 0xD50
+#define BHND_PCIE2_OMAP2_UPPER 0xD54
+#define BHND_PCIE2_FUNC1_IARR1_SIZE 0xD58
+#define BHND_PCIE2_FUNC1_IARR2_SIZE 0xD5C
+#define BHND_PCIE2_MEM_CONTROL 0xF00
+#define BHND_PCIE2_MEM_ECC_ERRLOG0 0xF04
+#define BHND_PCIE2_MEM_ECC_ERRLOG1 0xF08
+#define BHND_PCIE2_LINK_STATUS 0xF0C
+#define BHND_PCIE2_STRAP_STATUS 0xF10
+#define BHND_PCIE2_RESET_STATUS 0xF14
+#define BHND_PCIE2_RESETEN_IN_LINKDOWN 0xF18
+#define BHND_PCIE2_MISC_INTR_EN 0xF1C
+#define BHND_PCIE2_TX_DEBUG_CFG 0xF20
+#define BHND_PCIE2_MISC_CONFIG 0xF24
+#define BHND_PCIE2_MISC_STATUS 0xF28
+#define BHND_PCIE2_INTR_EN 0xF30
+#define BHND_PCIE2_INTR_CLEAR 0xF34
+#define BHND_PCIE2_INTR_STATUS 0xF38
+
+/* BHND_PCIE2_MDIO_CTL */
+#define BHND_PCIE2_MDIOCTL_DIVISOR_MASK 0x7f /* clock to be used on MDIO */
+#define BHND_PCIE2_MDIOCTL_DIVISOR_VAL 0x2
+#define BHND_PCIE2_MDIOCTL_REGADDR_SHIFT 8 /* Regaddr shift */
+#define BHND_PCIE2_MDIOCTL_REGADDR_MASK 0x00FFFF00 /* Regaddr Mask */
+#define BHND_PCIE2_MDIOCTL_DEVADDR_SHIFT 24 /* Physmedia devaddr shift */
+#define BHND_PCIE2_MDIOCTL_DEVADDR_MASK 0x0f000000 /* Physmedia devaddr Mask */
+#define BHND_PCIE2_MDIOCTL_SLAVE_BYPASS 0x10000000 /* IP slave bypass */
+#define BHND_PCIE2_MDIOCTL_READ 0x20000000 /* IP slave bypass */
+
+/* BHND_PCIE2_MDIO_DATA */
+#define BHND_PCIE2_MDIODATA_DONE 0x80000000 /* rd/wr transaction done */
+#define BHND_PCIE2_MDIODATA_MASK 0x7FFFFFFF /* rd/wr transaction data */
+#define BHND_PCIE2_MDIODATA_DEVADDR_SHIFT 4 /* Physmedia devaddr shift */
+
+/* BHND_PCIE2_DMA[0-4]_HOST2DEV_(TX|RX) per-channel register offsets */
+#define BHND_PCIE2_DMA_CTRL 0x0 /**< enable, et al */
+#define BHND_PCIE2_DMA_PTR 0x4 /**< last descriptor posted to chip */
+#define BHND_PCIE2_DMA_ADDRL 0x8 /**< descriptor ring base address low 32-bits (8K aligned) */
+#define BHND_PCIE2_DMA_ADDRH 0xC /**< descriptor ring base address bits 63:32 (8K aligned) */
+#define BHND_PCIE2_DMA_STATUS0 0x10 /**< current descriptor, xmt state */
+#define BHND_PCIE2_DMA_STATUS1 0x10 /**< active descriptor, xmt error */
+
+
+#endif /* _BHND_CORES_PCIE2_BHND_PCIE2_REG_H_ */
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2_var.h
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2_var.h
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BHND_CORES_PCIE2_BHND_PCIE2_VAR_H_
+#define _BHND_CORES_PCIE2_BHND_PCIE2_VAR_H_
+
+#include <sys/param.h>
+#include <sys/bus.h>
+
+/*
+ * Shared PCIe-G2 Bridge/Host Bridge definitions.
+ */
+
+DECLARE_CLASS(bhnd_pcie2_driver);
+struct bhnd_pcie2_softc;
+
+int bhnd_pcie2_generic_probe(device_t dev);
+int bhnd_pcie2_generic_attach(device_t dev);
+int bhnd_pcie2_generic_detach(device_t dev);
+int bhnd_pcie2_generic_suspend(device_t dev);
+int bhnd_pcie2_generic_resume(device_t dev);
+
+
+uint32_t bhnd_pcie2_read_proto_reg(struct bhnd_pcie2_softc *sc,
+ uint32_t addr);
+void bhnd_pcie2_write_proto_reg(struct bhnd_pcie2_softc *sc,
+ uint32_t addr, uint32_t val);
+int bhnd_pcie2_mdio_read(struct bhnd_pcie2_softc *sc, int phy,
+ int reg);
+int bhnd_pcie2_mdio_write(struct bhnd_pcie2_softc *sc, int phy,
+ int reg, int val);
+int bhnd_pcie2_mdio_read_ext(struct bhnd_pcie2_softc *sc, int phy,
+ int devaddr, int reg);
+int bhnd_pcie2_mdio_write_ext(struct bhnd_pcie2_softc *sc,
+ int phy, int devaddr, int reg, int val);
+
+/**
+ * bhnd_pcie2 child device info
+ */
+struct bhnd_pcie2_devinfo {
+ struct resource_list resources;
+};
+
+/*
+ * Generic PCIe-G2 bridge/end-point driver state.
+ *
+ * Must be first member of all subclass softc structures.
+ */
+struct bhnd_pcie2_softc {
+ device_t dev; /**< pci device */
+ uint32_t quirks; /**< quirk flags */
+
+ struct mtx mtx; /**< state mutex used to protect
+ interdependent register
+ accesses. */
+
+ struct bhnd_resource *mem_res; /**< device register block. */
+ int mem_rid; /**< register block RID */
+};
+
+
+#define BHND_PCIE2_LOCK_INIT(sc) \
+ mtx_init(&(sc)->mtx, device_get_nameunit((sc)->dev), \
+ "BHND PCIe-G2 driver lock", MTX_DEF)
+#define BHND_PCIE2_LOCK(sc) mtx_lock(&(sc)->mtx)
+#define BHND_PCIE2_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
+#define BHND_PCIE2_LOCK_ASSERT(sc, what) mtx_assert(&(sc)->mtx, what)
+#define BHND_PCIE2_LOCK_DESTROY(sc) mtx_destroy(&(sc)->mtx)
+
+#endif /* _BHND_CORES_PCIE2_BHND_PCIE2_VAR_H_ */
\ No newline at end of file
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2b.c
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2b.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2015 Landon Fuller <landon@landonf.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Broadcom PCI/PCIe-Gen1 Host-PCI bridge.
+ *
+ * This driver handles all interactions with PCI bridge cores operating in
+ * root complex mode.
+ */
+
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <machine/resource.h>
+
+#include <dev/bhnd/bhnd.h>
+
+#include "bhnd_pcie2_reg.h"
+#include "bhnd_pcie2b_var.h"
+
+static int
+bhnd_pcie2b_attach(device_t dev)
+{
+ // TODO
+ return (bhnd_pcie2_generic_attach(dev));
+}
+
+static int
+bhnd_pcie2b_detach(device_t dev)
+{
+ // TODO
+ return (bhnd_pcie2_generic_detach(dev));
+}
+
+static int
+bhnd_pcie2b_suspend(device_t dev)
+{
+ return (bhnd_pcie2_generic_suspend(dev));
+}
+
+static int
+bhnd_pcie2b_resume(device_t dev)
+{
+ return (bhnd_pcie2_generic_resume(dev));
+}
+
+static device_method_t bhnd_pcie2b_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_attach, bhnd_pcie2b_attach),
+ DEVMETHOD(device_detach, bhnd_pcie2b_detach),
+ DEVMETHOD(device_suspend, bhnd_pcie2b_suspend),
+ DEVMETHOD(device_resume, bhnd_pcie2b_resume),
+ DEVMETHOD_END
+};
+
+DEFINE_CLASS_1(pcib, bhnd_pcie2b_driver, bhnd_pcie2b_methods,
+ sizeof(struct bhnd_pcie2b_softc), bhnd_pcie2_driver);
+
+static devclass_t pcib_devclass;
+DRIVER_MODULE(bhnd_pcie2b, bhnd, bhnd_pcie2b_driver, pcib_devclass, 0, 0);
+
+MODULE_VERSION(bhnd_pcie2b, 1);
+MODULE_DEPEND(bhnd_pcie2b, bhnd, 1, 1, 1);
+MODULE_DEPEND(bhnd_pcie2b, bhnd_pcie2, 1, 1, 1);
+MODULE_DEPEND(bhnd_pcie2b, pci, 1, 1, 1);
Index: sys/dev/bhnd/cores/pcie2/bhnd_pcie2b_var.h
===================================================================
--- /dev/null
+++ sys/dev/bhnd/cores/pcie2/bhnd_pcie2b_var.h
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
+ * redistribution must be conditioned upon including a substantially
+ * similar Disclaimer requirement for further binary redistribution.
+ *
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
+ * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _BHND_CORES_PCIE2_BHND_PCIE2BVAR_H_
+#define _BHND_CORES_PCIE2_BHND_PCIE2BVAR_H_
+
+#include "bhnd_pcie2_var.h"
+
+/* PCIe-G2 bridge driver-specific state */
+struct bhnd_pcie2b_softc {
+ struct bhnd_pcie2_softc sc_common;
+};
+
+#endif /* _BHND_CORES_PCIE2_BHND_PCIE2BVAR_H_ */
\ No newline at end of file
Index: sys/dev/bhnd/siba/siba.c
===================================================================
--- sys/dev/bhnd/siba/siba.c
+++ sys/dev/bhnd/siba/siba.c
@@ -55,15 +55,13 @@
siba_attach(device_t dev)
{
struct siba_devinfo *dinfo;
+ struct siba_softc *sc;
device_t *devs;
int ndevs;
int error;
-
- // TODO: We need to set the initiator timeout for the
- // core that will be issuing requests to non-memory locations.
- //
- // In the case of a bridged device, this is the hostb core.
- // On a non-bridged device, this will be the CPU.
+
+ sc = device_get_softc(dev);
+ sc->dev = dev;
/* Fetch references to the siba SIBA_CFG* blocks for all
* registered devices */
@@ -144,6 +142,18 @@
return (bhnd_generic_detach(dev));
}
+int
+siba_resume(device_t dev)
+{
+ return (bhnd_generic_resume(dev));
+}
+
+int
+siba_suspend(device_t dev)
+{
+ return (bhnd_generic_suspend(dev));
+}
+
static int
siba_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
{
@@ -663,6 +673,8 @@
DEVMETHOD(device_probe, siba_probe),
DEVMETHOD(device_attach, siba_attach),
DEVMETHOD(device_detach, siba_detach),
+ DEVMETHOD(device_resume, siba_resume),
+ DEVMETHOD(device_suspend, siba_suspend),
/* Bus interface */
DEVMETHOD(bus_child_deleted, siba_child_deleted),
Index: sys/dev/bhnd/siba/siba_bhndb.c
===================================================================
--- sys/dev/bhnd/siba/siba_bhndb.c
+++ sys/dev/bhnd/siba/siba_bhndb.c
@@ -34,11 +34,13 @@
#include <sys/kernel.h>
#include <sys/bus.h>
#include <sys/module.h>
+#include <sys/systm.h>
#include <dev/bhnd/bhnd_ids.h>
#include <dev/bhnd/bhndb/bhndbvar.h>
#include <dev/bhnd/bhndb/bhndb_hwdata.h>
+#include "sibareg.h"
#include "sibavar.h"
/*
@@ -56,6 +58,20 @@
// than delegating to our parent bhndb device.
//
+static int siba_bhndb_wars_hwup(struct siba_softc *sc);
+
+enum {
+ /** When PCIe-bridged, the D11 core's initiator request
+ * timeout must be disabled to prevent D11 from entering a
+ * RESP_TIMEOUT error state. */
+ SIBA_QUIRK_PCIE_D11_SB_TIMEOUT = (1<<0)
+};
+
+static struct bhnd_chip_quirk chip_quirks[] = {
+ {{ BHND_CHIP_IR(4311, HWREV_EQ(2)) }, SIBA_QUIRK_PCIE_D11_SB_TIMEOUT },
+ {{ BHND_CHIP_IR(4312, HWREV_EQ(0)) }, SIBA_QUIRK_PCIE_D11_SB_TIMEOUT },
+};
+
static int
siba_bhndb_probe(device_t dev)
{
@@ -94,7 +110,30 @@
sc->hostb_dev = BHNDB_FIND_HOSTB_DEVICE(device_get_parent(dev), dev);
/* Call our superclass' implementation */
- return (siba_attach(dev));
+ if ((error = siba_attach(dev)))
+ return (error);
+
+ /* Apply attach/resume work-arounds */
+ if ((error = siba_bhndb_wars_hwup(sc)))
+ return (error);
+
+ return (0);
+}
+
+static int
+siba_bhndb_resume(device_t dev)
+{
+ struct siba_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+
+ /* Apply attach/resume work-arounds */
+ if ((error = siba_bhndb_wars_hwup(sc)))
+ return (error);
+
+ /* Call our superclass' implementation */
+ return (siba_resume(dev));
}
/* Suspend all references to the device's cfg register blocks */
@@ -180,10 +219,67 @@
return (BHNDB_POPULATE_BOARD_INFO(device_get_parent(dev), dev, info));
}
+/* Work-around implementation for SIBA_QUIRK_PCIE_D11_SB_TIMEOUT */
+static int
+siba_bhndb_wars_pcie_clear_d11_timeout(struct siba_softc *sc)
+{
+ struct siba_devinfo *dinfo;
+ device_t d11;
+ uint32_t imcfg;
+
+ /* Only applies when bridged by PCIe */
+ if (bhnd_get_class(sc->hostb_dev) != BHND_DEVCLASS_PCIE)
+ return (0);
+
+ /* Only applies if there's a D11 core */
+ d11 = bhnd_match_child(sc->dev, &(struct bhnd_core_match){
+ .vendor = BHND_MFGID_BCM,
+ .device = BHND_COREID_D11,
+ .hwrev = BHND_HWREV_ANY,
+ .class = BHND_DEVCLASS_INVALID,
+ .unit = 0
+ });
+ if (d11 == NULL)
+ return (0);
+
+ /* Clear initiator timeout in D11's CFG0 block */
+ dinfo = device_get_ivars(d11);
+ KASSERT(dinfo->cfg[0] != NULL, ("missing core config mapping"));
+
+ imcfg = bhnd_bus_read_4(dinfo->cfg[0], SIBA_CFG0_IMCONFIGLOW);
+ imcfg &= ~SIBA_IMCL_RTO_MASK;
+
+ bhnd_bus_write_4(dinfo->cfg[0], SIBA_CFG0_IMCONFIGLOW, imcfg);
+
+ return (0);
+}
+
+/**
+ * Apply any hardware workarounds that are required upon attach or resume
+ * of the bus.
+ */
+static int
+siba_bhndb_wars_hwup(struct siba_softc *sc)
+{
+ uint32_t quirks;
+ int error;
+
+ quirks = bhnd_chip_quirks(sc->hostb_dev, chip_quirks);
+
+ if (quirks & SIBA_QUIRK_PCIE_D11_SB_TIMEOUT) {
+ if ((error = siba_bhndb_wars_pcie_clear_d11_timeout(sc)))
+ return (error);
+ }
+
+ return (0);
+}
+
+
static device_method_t siba_bhndb_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, siba_bhndb_probe),
DEVMETHOD(device_attach, siba_bhndb_attach),
+ DEVMETHOD(device_resume, siba_bhndb_resume),
/* Bus interface */
DEVMETHOD(bus_suspend_child, siba_bhndb_suspend_child),
Index: sys/dev/bhnd/siba/sibavar.h
===================================================================
--- sys/dev/bhnd/siba/sibavar.h
+++ sys/dev/bhnd/siba/sibavar.h
@@ -53,6 +53,8 @@
int siba_probe(device_t dev);
int siba_attach(device_t dev);
int siba_detach(device_t dev);
+int siba_resume(device_t dev);
+int siba_suspend(device_t dev);
uint16_t siba_get_bhnd_mfgid(uint16_t ocp_vendor);
@@ -145,6 +147,7 @@
/** siba(4) per-instance state */
struct siba_softc {
struct bhnd_softc bhnd_sc; /**< bhnd state */
+ device_t dev; /**< siba device */
device_t hostb_dev; /**< host bridge core, or NULL */
};
Index: sys/modules/bhnd/cores/bhnd_pci/Makefile
===================================================================
--- sys/modules/bhnd/cores/bhnd_pci/Makefile
+++ sys/modules/bhnd/cores/bhnd_pci/Makefile
@@ -1,9 +1,10 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/pci
+.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/pcie2
KMOD= bhnd_pci
-SRCS= bhnd_pci.c
+SRCS= bhnd_pci.c bhnd_pcie2.c
SRCS+= device_if.h bus_if.h bhnd_bus_if.h
.include <bsd.kmod.mk>
Index: sys/modules/bhnd/cores/bhnd_pci_hostb/Makefile
===================================================================
--- sys/modules/bhnd/cores/bhnd_pci_hostb/Makefile
+++ sys/modules/bhnd/cores/bhnd_pci_hostb/Makefile
@@ -1,9 +1,11 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/pci
+.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/pcie2
KMOD= bhnd_pci_hostb
-SRCS= bhnd_pci_hostb.c
-SRCS+= device_if.h bus_if.h bhnd_bus_if.h
+SRCS= bhnd_pci_hostb.c bhnd_pcie2_hostb.c
+SRCS+= device_if.h bus_if.h pci_if.h \
+ bhnd_bus_if.h bhnd_chipc_if.h
.include <bsd.kmod.mk>
Index: sys/modules/bhnd/cores/bhnd_pcib/Makefile
===================================================================
--- sys/modules/bhnd/cores/bhnd_pcib/Makefile
+++ sys/modules/bhnd/cores/bhnd_pcib/Makefile
@@ -1,9 +1,11 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/pci
+.PATH: ${.CURDIR}/../../../../dev/bhnd/cores/pcie2
KMOD= bhnd_pcib
-SRCS= bhnd_pcib.c
-SRCS+= device_if.h bus_if.h bhnd_bus_if.h
+SRCS= bhnd_pcib.c bhnd_pcie2b.c
+SRCS+= device_if.h bus_if.h pci_if.h \
+ bhnd_bus_if.h
.include <bsd.kmod.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 11, 4:18 PM (19 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
23583742
Default Alt Text
D6377.id16435.diff (84 KB)
Attached To
Mode
D6377: Finish bhnd(4) PCI/PCIe-G1 hostb support
Attached
Detach File
Event Timeline
Log In to Comment