From owner-svn-src-all@freebsd.org Tue May 17 06:52:56 2016 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 34F63B3E61D; Tue, 17 May 2016 06:52:56 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id C9B1D1898; Tue, 17 May 2016 06:52:55 +0000 (UTC) (envelope-from adrian@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id u4H6qtwo024912; Tue, 17 May 2016 06:52:55 GMT (envelope-from adrian@FreeBSD.org) Received: (from adrian@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id u4H6qsmQ024900; Tue, 17 May 2016 06:52:54 GMT (envelope-from adrian@FreeBSD.org) Message-Id: <201605170652.u4H6qsmQ024900@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: adrian set sender to adrian@FreeBSD.org using -f From: Adrian Chadd Date: Tue, 17 May 2016 06:52:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r300015 - in head/sys: conf dev/bhnd dev/bhnd/bhndb dev/bhnd/cores/chipc dev/bhnd/cores/pci dev/bhnd/cores/pcie2 dev/bhnd/siba modules/bhnd/cores/bhnd_pci modules/bhnd/cores/bhnd_pci_ho... X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 17 May 2016 06:52:56 -0000 Author: adrian Date: Tue May 17 06:52:53 2016 New Revision: 300015 URL: https://svnweb.freebsd.org/changeset/base/300015 Log: [bhnd] Finish bhnd(4) PCI/PCIe-G1 hostb support. Now that we've got access to SPROM and can access board identification, this implements all known remaining hardware work-arounds for the bhnd(4) PCI and PCIe-G1 cores operating endpoint mode. Additionally, this adds an initial set of skeleton PCIe-G2 hostb and pcib drivers, required by fullmac and newer softmac devices. Submitted by: Landon Fuller Differential Revision: https://reviews.freebsd.org/D6377 Added: head/sys/dev/bhnd/cores/pcie2/ head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2.c (contents, props changed) head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c (contents, props changed) head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_hostbvar.h (contents, props changed) head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_reg.h (contents, props changed) head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2_var.h (contents, props changed) head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2b.c (contents, props changed) head/sys/dev/bhnd/cores/pcie2/bhnd_pcie2b_var.h (contents, props changed) Modified: head/sys/conf/files head/sys/dev/bhnd/bhnd.h head/sys/dev/bhnd/bhnd_ids.h head/sys/dev/bhnd/bhnd_subr.c head/sys/dev/bhnd/bhndb/bhndb_pci.c head/sys/dev/bhnd/bhndb/bhndb_pcireg.h head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m head/sys/dev/bhnd/cores/chipc/chipc.c head/sys/dev/bhnd/cores/pci/bhnd_pci.c head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h head/sys/dev/bhnd/cores/pci/bhnd_pcib.c head/sys/dev/bhnd/cores/pci/bhnd_pcireg.h head/sys/dev/bhnd/siba/siba.c head/sys/dev/bhnd/siba/siba_bhndb.c head/sys/dev/bhnd/siba/sibavar.h head/sys/modules/bhnd/cores/bhnd_pci/Makefile head/sys/modules/bhnd/cores/bhnd_pci_hostb/Makefile head/sys/modules/bhnd/cores/bhnd_pcib/Makefile Modified: head/sys/conf/files ============================================================================== --- head/sys/conf/files Tue May 17 06:45:25 2016 (r300014) +++ head/sys/conf/files Tue May 17 06:52:53 2016 (r300015) @@ -1142,6 +1142,9 @@ dev/bhnd/cores/chipc/bhnd_chipc_if.m opt 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 Modified: head/sys/dev/bhnd/bhnd.h ============================================================================== --- head/sys/dev/bhnd/bhnd.h Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/bhnd.h Tue May 17 06:52:53 2016 (r300015) @@ -318,8 +318,8 @@ struct bhnd_chip_match { .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 @@ struct bhnd_chip_match { /** 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_match_child(device_t de 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, Modified: head/sys/dev/bhnd/bhnd_ids.h ============================================================================== --- head/sys/dev/bhnd/bhnd_ids.h Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/bhnd_ids.h Tue May 17 06:52:53 2016 (r300015) @@ -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 Modified: head/sys/dev/bhnd/bhnd_subr.c ============================================================================== --- head/sys/dev/bhnd/bhnd_subr.c Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/bhnd_subr.c Tue May 17 06:52:53 2016 (r300015) @@ -350,6 +350,56 @@ done: } /** + * 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. Modified: head/sys/dev/bhnd/bhndb/bhndb_pci.c ============================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pci.c Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/bhndb/bhndb_pci.c Tue May 17 06:52:53 2016 (r300015) @@ -37,9 +37,10 @@ __FBSDID("$FreeBSD$"); * 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 @@ -482,6 +483,35 @@ bhndb_pci_populate_board_info(device_t d 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 @@ bhndb_disable_pci_clocks(struct bhndb_pc 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 @@ DEFINE_CLASS_1(bhndb, bhndb_pci_driver, 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); Modified: head/sys/dev/bhnd/bhndb/bhndb_pcireg.h ============================================================================== --- head/sys/dev/bhnd/bhndb/bhndb_pcireg.h Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/bhndb/bhndb_pcireg.h Tue May 17 06:52:53 2016 (r300015) @@ -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 */ Modified: head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m ============================================================================== --- head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/cores/chipc/bhnd_chipc_if.m Tue May 17 06:52:53 2016 (r300015) @@ -43,4 +43,23 @@ INTERFACE bhnd_chipc; */ 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; +} Modified: head/sys/dev/bhnd/cores/chipc/chipc.c ============================================================================== --- head/sys/dev/bhnd/cores/chipc/chipc.c Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/cores/chipc/chipc.c Tue May 17 06:52:53 2016 (r300015) @@ -489,20 +489,38 @@ chipc_nvram_setvar(device_t dev, const c 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 }; Modified: head/sys/dev/bhnd/cores/pci/bhnd_pci.c ============================================================================== --- head/sys/dev/bhnd/cores/pci/bhnd_pci.c Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/cores/pci/bhnd_pci.c Tue May 17 06:52:53 2016 (r300015) @@ -429,8 +429,7 @@ bhnd_pcie_mdio_read_ext(struct bhnd_pci_ 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 @@ bhnd_pcie_mdio_read_ext(struct bhnd_pci_ /* 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 @@ bhnd_pcie_mdio_write_ext(struct bhnd_pci 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 @@ bhnd_pcie_mdio_write_ext(struct bhnd_pci /* 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); Modified: head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c ============================================================================== --- head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c Tue May 17 06:52:53 2016 (r300015) @@ -56,28 +56,43 @@ __FBSDID("$FreeBSD$"); #include -#include "bhnd_pcireg.h" -#include "bhnd_pci_hostbvar.h" +#include +#include -#define BHND_PCI_ASSERT_QUIRK(_sc, _name) \ - KASSERT((_sc)->quirks & (_name), ("quirk " __STRING(_name) " not set")) +#include +#include -#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 @@ static const struct bhnd_device_quirk bh 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 @@ static const struct bhnd_device_quirk bh { 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 @@ static const struct bhnd_chip_quirk bhnd #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 @@ bhnd_pci_hostb_attach(device_t dev) 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 @@ bhnd_pci_hostb_detach(device_t dev) 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 @@ bhnd_pci_hostb_suspend(device_t dev) 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 @@ bhnd_pci_hostb_resume(device_t dev) 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 @@ bhnd_pci_hostb_resume(device_t dev) 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 @@ bhnd_pci_wars_early_once(struct bhnd_pci 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 @@ bhnd_pci_wars_early_once(struct bhnd_pci * 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_wars_hwup(struct bhnd_pcihb_sof 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 @@ bhnd_pci_wars_hwup(struct bhnd_pcihb_sof } } + /* 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 @@ bhnd_pci_wars_hwup(struct bhnd_pcihb_sof * 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_wars_hwdown(struct bhnd_pcihb_s 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 @@ static device_method_t bhnd_pci_hostb_me 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); Modified: head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h ============================================================================== --- head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h Tue May 17 06:45:25 2016 (r300014) +++ head/sys/dev/bhnd/cores/pci/bhnd_pci_hostbvar.h Tue May 17 06:52:53 2016 (r300015) @@ -43,7 +43,7 @@ DECLARE_CLASS(bhnd_pci_hostb_driver); -/* +/** * PCI/PCIe-Gen1 endpoint-mode device quirks */ enum { @@ -56,7 +56,6 @@ enum { */ BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST = (1<<1), - /** * SBTOPCI_RC_READMULTI must be set on the SSB_PCICORE_SBTOPCI2 * register. @@ -74,18 +73,24 @@ enum { 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 @@ enum { * 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 *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***