bhnd_pci_hostb.c revision 300015
1296077Sadrian/*- 2296077Sadrian * Copyright (c) 2015 Landon Fuller <landon@landonf.org> 3296077Sadrian * All rights reserved. 4296077Sadrian * 5296077Sadrian * Redistribution and use in source and binary forms, with or without 6296077Sadrian * modification, are permitted provided that the following conditions 7296077Sadrian * are met: 8296077Sadrian * 1. Redistributions of source code must retain the above copyright 9296077Sadrian * notice, this list of conditions and the following disclaimer, 10296077Sadrian * without modification. 11296077Sadrian * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12296077Sadrian * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13296077Sadrian * redistribution must be conditioned upon including a substantially 14296077Sadrian * similar Disclaimer requirement for further binary redistribution. 15296077Sadrian * 16296077Sadrian * NO WARRANTY 17296077Sadrian * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18296077Sadrian * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19296077Sadrian * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20296077Sadrian * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21296077Sadrian * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22296077Sadrian * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23296077Sadrian * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24296077Sadrian * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25296077Sadrian * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26296077Sadrian * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27296077Sadrian * THE POSSIBILITY OF SUCH DAMAGES. 28296077Sadrian */ 29296077Sadrian 30296077Sadrian#include <sys/cdefs.h> 31296077Sadrian__FBSDID("$FreeBSD: head/sys/dev/bhnd/cores/pci/bhnd_pci_hostb.c 300015 2016-05-17 06:52:53Z adrian $"); 32296077Sadrian 33296077Sadrian/* 34298479Sadrian * Broadcom BHND PCI/PCIe-Gen1 PCI-Host Bridge. 35296077Sadrian * 36298479Sadrian * This driver handles all interactions with PCI bridge cores operating in 37298479Sadrian * endpoint mode. 38298479Sadrian * 39298479Sadrian * Host-level PCI operations are handled at the bhndb bridge level by the 40298479Sadrian * bhndb_pci driver. 41296077Sadrian */ 42296077Sadrian 43296077Sadrian#include <sys/param.h> 44296077Sadrian#include <sys/kernel.h> 45298479Sadrian 46298479Sadrian#include <sys/malloc.h> 47298479Sadrian 48296077Sadrian#include <sys/bus.h> 49296077Sadrian#include <sys/module.h> 50298479Sadrian 51296077Sadrian#include <sys/systm.h> 52296077Sadrian 53296077Sadrian#include <machine/bus.h> 54296077Sadrian#include <sys/rman.h> 55296077Sadrian#include <machine/resource.h> 56296077Sadrian 57296077Sadrian#include <dev/bhnd/bhnd.h> 58296077Sadrian 59300015Sadrian#include <dev/pci/pcireg.h> 60300015Sadrian#include <dev/pci/pcivar.h> 61300015Sadrian 62300015Sadrian#include <dev/bhnd/cores/chipc/chipc.h> 63300015Sadrian#include <dev/bhnd/cores/chipc/chipcreg.h> 64300015Sadrian 65298479Sadrian#include "bhnd_pcireg.h" 66298479Sadrian#include "bhnd_pci_hostbvar.h" 67298479Sadrian 68298479Sadrianstatic const struct bhnd_device_quirk bhnd_pci_quirks[]; 69298479Sadrianstatic const struct bhnd_device_quirk bhnd_pcie_quirks[]; 70300015Sadrianstatic const struct bhnd_chip_quirk bhnd_pci_chip_quirks[]; 71299996Sadrianstatic const struct bhnd_chip_quirk bhnd_pcie_chip_quirks[]; 72298479Sadrian 73300015Sadrian/* Device driver work-around variations */ 74300015Sadriantypedef enum { 75300015Sadrian BHND_PCI_WAR_ATTACH, /**< apply attach workarounds */ 76300015Sadrian BHND_PCI_WAR_RESUME, /**< apply resume workarounds */ 77300015Sadrian BHND_PCI_WAR_SUSPEND, /**< apply suspend workarounds */ 78300015Sadrian BHND_PCI_WAR_DETACH /**< apply detach workarounds */ 79300015Sadrian} bhnd_pci_war_state; 80300015Sadrian 81298479Sadrianstatic int bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc); 82300015Sadrianstatic int bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, 83300015Sadrian bhnd_pci_war_state state); 84300015Sadrianstatic int bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, 85300015Sadrian bhnd_pci_war_state state); 86298479Sadrian 87298479Sadrian/* 88298479Sadrian * device/quirk tables 89298479Sadrian */ 90300015Sadrian 91300015Sadrian#define BHND_PCI_DEV(_core, _quirks, _chip_quirks) \ 92300015Sadrian BHND_DEVICE(_core, "", _quirks, _chip_quirks, BHND_DF_HOSTB) 93300015Sadrian 94298479Sadrianstatic const struct bhnd_device bhnd_pci_devs[] = { 95300015Sadrian BHND_PCI_DEV(PCI, bhnd_pci_quirks, bhnd_pci_chip_quirks), 96299996Sadrian BHND_PCI_DEV(PCIE, bhnd_pcie_quirks, bhnd_pcie_chip_quirks), 97298479Sadrian BHND_DEVICE_END 98296077Sadrian}; 99296077Sadrian 100298479Sadrianstatic const struct bhnd_device_quirk bhnd_pci_quirks[] = { 101298479Sadrian { BHND_HWREV_ANY, BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST }, 102298479Sadrian { BHND_HWREV_GTE(11), BHND_PCI_QUIRK_SBTOPCI2_READMULTI | 103298479Sadrian BHND_PCI_QUIRK_CLKRUN_DSBL }, 104298479Sadrian BHND_DEVICE_QUIRK_END 105298479Sadrian}; 106298479Sadrian 107300015Sadrianstatic const struct bhnd_chip_quirk bhnd_pci_chip_quirks[] = { 108300015Sadrian /* BCM4321CB2 boards that require 960ns latency timer override */ 109300015Sadrian {{ BHND_CHIP_BTYPE(BCM4321CB2) }, 110300015Sadrian BHND_PCI_QUIRK_960NS_LATTIM_OVR }, 111300015Sadrian {{ BHND_CHIP_BTYPE(BCM4321CB2_AG) }, 112300015Sadrian BHND_PCI_QUIRK_960NS_LATTIM_OVR }, 113300015Sadrian 114300015Sadrian BHND_CHIP_QUIRK_END 115300015Sadrian}; 116300015Sadrian 117298479Sadrianstatic const struct bhnd_device_quirk bhnd_pcie_quirks[] = { 118298479Sadrian { BHND_HWREV_EQ (0), BHND_PCIE_QUIRK_SDR9_L0s_HANG }, 119300015Sadrian { BHND_HWREV_RANGE (0,1), BHND_PCIE_QUIRK_UR_STATUS_FIX }, 120298479Sadrian { BHND_HWREV_EQ (1), BHND_PCIE_QUIRK_PCIPM_REQEN }, 121298479Sadrian 122300015Sadrian { BHND_HWREV_RANGE (3,5), BHND_PCIE_QUIRK_ASPM_OVR | 123298479Sadrian BHND_PCIE_QUIRK_SDR9_POLARITY | 124298479Sadrian BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY }, 125298479Sadrian 126298479Sadrian { BHND_HWREV_LTE (6), BHND_PCIE_QUIRK_L1_IDLE_THRESH }, 127298479Sadrian { BHND_HWREV_GTE (6), BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET }, 128298479Sadrian { BHND_HWREV_EQ (7), BHND_PCIE_QUIRK_SERDES_NOPLLDOWN }, 129298479Sadrian { BHND_HWREV_GTE (8), BHND_PCIE_QUIRK_L1_TIMER_PERF }, 130300015Sadrian 131300015Sadrian { BHND_HWREV_LTE (17), BHND_PCIE_QUIRK_MAX_MRRS_128 }, 132300015Sadrian 133298479Sadrian BHND_DEVICE_QUIRK_END 134298479Sadrian}; 135298479Sadrian 136299996Sadrianstatic const struct bhnd_chip_quirk bhnd_pcie_chip_quirks[] = { 137299996Sadrian /* Apple boards on which BHND_BFL2_PCIEWAR_OVR should be assumed 138299996Sadrian * to be set. */ 139300015Sadrian {{ BHND_CHIP_BVENDOR (PCI_VENDOR_APPLE), 140300015Sadrian BHND_CHIP_SROMREV (HWREV_EQ(4)), 141300015Sadrian BHND_CHIP_BREV (HWREV_LTE(0x71)) }, 142300015Sadrian BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN }, 143299996Sadrian 144300015Sadrian /* Apple BCM4322 boards that require 700mV SerDes TX drive strength. */ 145300015Sadrian {{ BHND_CHIP_BVT (PCI_VENDOR_APPLE, BCM94322X9) }, 146300015Sadrian BHND_PCIE_QUIRK_SERDES_TXDRV_700MV }, 147300015Sadrian 148300015Sadrian /* Apple BCM4331 board-specific quirks */ 149300015Sadrian#define BHND_APPLE_4331_QUIRK(_board, ...) \ 150300015Sadrian {{ BHND_CHIP_ID (4331), \ 151300015Sadrian BHND_CHIP_BVT (PCI_VENDOR_APPLE, _board), }, \ 152300015Sadrian __VA_ARGS__ } 153300015Sadrian 154300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X19, 155300015Sadrian BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 156300015Sadrian 157300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X28, 158300015Sadrian BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 159300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X28B, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 160300015Sadrian 161300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X29B, 162300015Sadrian BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 163300015Sadrian 164300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X19C, 165300015Sadrian BHND_PCIE_QUIRK_SERDES_TXDRV_MAX|BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 166300015Sadrian 167300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X29D, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 168300015Sadrian BHND_APPLE_4331_QUIRK(BCM94331X33, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 169300015Sadrian#undef BHND_APPLE_4331_QUIRK 170300015Sadrian 171299996Sadrian BHND_CHIP_QUIRK_END 172299996Sadrian}; 173299996Sadrian 174298479Sadrian#define BHND_PCI_SOFTC(_sc) (&((_sc)->common)) 175298479Sadrian 176298479Sadrian#define BHND_PCI_READ_2(_sc, _reg) \ 177298479Sadrian bhnd_bus_read_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg)) 178298479Sadrian 179298479Sadrian#define BHND_PCI_READ_4(_sc, _reg) \ 180298479Sadrian bhnd_bus_read_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg)) 181298479Sadrian 182298479Sadrian#define BHND_PCI_WRITE_2(_sc, _reg, _val) \ 183298479Sadrian bhnd_bus_write_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val)) 184298479Sadrian 185298479Sadrian#define BHND_PCI_WRITE_4(_sc, _reg, _val) \ 186298479Sadrian bhnd_bus_write_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val)) 187298479Sadrian 188298479Sadrian#define BHND_PCI_PROTO_READ_4(_sc, _reg) \ 189298479Sadrian bhnd_pcie_read_proto_reg(BHND_PCI_SOFTC(_sc), (_reg)) 190298479Sadrian 191298479Sadrian#define BHND_PCI_PROTO_WRITE_4(_sc, _reg, _val) \ 192298479Sadrian bhnd_pcie_write_proto_reg(BHND_PCI_SOFTC(_sc), (_reg), (_val)) 193298479Sadrian 194298479Sadrian#define BHND_PCI_MDIO_READ(_sc, _phy, _reg) \ 195298479Sadrian bhnd_pcie_mdio_read(BHND_PCI_SOFTC(_sc), (_phy), (_reg)) 196298479Sadrian 197298479Sadrian#define BHND_PCI_MDIO_WRITE(_sc, _phy, _reg, _val) \ 198298479Sadrian bhnd_pcie_mdio_write(BHND_PCI_SOFTC(_sc), (_phy), (_reg), (_val)) 199298479Sadrian 200300015Sadrian#define BHND_PCI_MDIO_READ_EXT(_sc, _phy, _devaddr, _reg) \ 201300015Sadrian bhnd_pcie_mdio_read_ext(BHND_PCI_SOFTC(_sc), (_phy), (_devaddr), (_reg)) 202300015Sadrian 203300015Sadrian#define BHND_PCI_MDIO_WRITE_EXT(_sc, _phy, _devaddr, _reg, _val) \ 204300015Sadrian bhnd_pcie_mdio_write_ext(BHND_PCI_SOFTC(_sc), (_phy), \ 205300015Sadrian (_devaddr), (_reg), (_val)) 206300015Sadrian 207298479Sadrian#define BPCI_REG_SET(_regv, _attr, _val) \ 208298479Sadrian BHND_PCI_REG_SET((_regv), BHND_ ## _attr, (_val)) 209298479Sadrian 210298479Sadrian#define BPCI_REG_GET(_regv, _attr) \ 211298479Sadrian BHND_PCI_REG_GET((_regv), BHND_ ## _attr) 212298479Sadrian 213298479Sadrian#define BPCI_CMN_REG_SET(_regv, _attr, _val) \ 214298479Sadrian BHND_PCI_CMN_REG_SET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv), \ 215298479Sadrian BHND_ ## _attr, (_val)) 216298479Sadrian 217298479Sadrian#define BPCI_CMN_REG_GET(_regv, _attr) \ 218298479Sadrian BHND_PCI_CMN_REG_GET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv), \ 219298479Sadrian BHND_ ## _attr) 220298479Sadrian 221296077Sadrianstatic int 222298479Sadrianbhnd_pci_hostb_attach(device_t dev) 223296077Sadrian{ 224298479Sadrian struct bhnd_pcihb_softc *sc; 225298479Sadrian int error; 226298479Sadrian 227298479Sadrian sc = device_get_softc(dev); 228300015Sadrian sc->dev = dev; 229298479Sadrian sc->quirks = bhnd_device_quirks(dev, bhnd_pci_devs, 230298479Sadrian sizeof(bhnd_pci_devs[0])); 231298479Sadrian 232300015Sadrian /* Find the host PCI bridge device */ 233300015Sadrian sc->pci_dev = bhnd_find_bridge_root(dev, devclass_find("pci")); 234300015Sadrian if (sc->pci_dev == NULL) { 235300015Sadrian device_printf(dev, "parent pci bridge device not found\n"); 236300015Sadrian return (ENXIO); 237300015Sadrian } 238300015Sadrian 239300015Sadrian /* Common setup */ 240298479Sadrian if ((error = bhnd_pci_generic_attach(dev))) 241298479Sadrian return (error); 242298479Sadrian 243298479Sadrian /* Apply early single-shot work-arounds */ 244300015Sadrian if ((error = bhnd_pci_wars_early_once(sc))) 245300015Sadrian goto failed; 246296077Sadrian 247298479Sadrian /* Apply attach/resume work-arounds */ 248300015Sadrian if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_ATTACH))) 249300015Sadrian goto failed; 250296077Sadrian 251298479Sadrian return (0); 252300015Sadrian 253300015Sadrianfailed: 254300015Sadrian bhnd_pci_generic_detach(dev); 255300015Sadrian return (error); 256296077Sadrian} 257296077Sadrian 258296077Sadrianstatic int 259298479Sadrianbhnd_pci_hostb_detach(device_t dev) 260296077Sadrian{ 261298479Sadrian struct bhnd_pcihb_softc *sc; 262298479Sadrian int error; 263298479Sadrian 264298479Sadrian sc = device_get_softc(dev); 265298479Sadrian 266298479Sadrian /* Apply suspend/detach work-arounds */ 267300015Sadrian if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_DETACH))) 268298479Sadrian return (error); 269298479Sadrian 270298479Sadrian return (bhnd_pci_generic_detach(dev)); 271296077Sadrian} 272296077Sadrian 273296077Sadrianstatic int 274298479Sadrianbhnd_pci_hostb_suspend(device_t dev) 275296077Sadrian{ 276298479Sadrian struct bhnd_pcihb_softc *sc; 277298479Sadrian int error; 278298479Sadrian 279298479Sadrian sc = device_get_softc(dev); 280298479Sadrian 281298479Sadrian /* Apply suspend/detach work-arounds */ 282300015Sadrian if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_SUSPEND))) 283298479Sadrian return (error); 284298479Sadrian 285298479Sadrian return (bhnd_pci_generic_suspend(dev)); 286298479Sadrian} 287298479Sadrian 288298479Sadrianstatic int 289298479Sadrianbhnd_pci_hostb_resume(device_t dev) 290298479Sadrian{ 291298479Sadrian struct bhnd_pcihb_softc *sc; 292298479Sadrian int error; 293298479Sadrian 294298479Sadrian sc = device_get_softc(dev); 295298479Sadrian 296298479Sadrian if ((error = bhnd_pci_generic_resume(dev))) 297298479Sadrian return (error); 298298479Sadrian 299298479Sadrian /* Apply attach/resume work-arounds */ 300300015Sadrian if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_RESUME))) { 301298479Sadrian bhnd_pci_generic_detach(dev); 302298479Sadrian return (error); 303298479Sadrian } 304298479Sadrian 305296077Sadrian return (0); 306296077Sadrian} 307296077Sadrian 308298479Sadrian/** 309298479Sadrian * Apply any hardware work-arounds that must be executed exactly once, early in 310298479Sadrian * the attach process. 311298479Sadrian * 312298479Sadrian * This must be called after core enumeration and discovery of all applicable 313298479Sadrian * quirks, but prior to probe/attach of any cores, parsing of 314298479Sadrian * SPROM, etc. 315298479Sadrian */ 316296077Sadrianstatic int 317298479Sadrianbhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc) 318296077Sadrian{ 319300015Sadrian int error; 320300015Sadrian 321300015Sadrian /* Set PCI latency timer */ 322300015Sadrian if (sc->quirks & BHND_PCI_QUIRK_960NS_LATTIM_OVR) { 323300015Sadrian pci_write_config(sc->pci_dev, PCIR_LATTIMER, 0x20 /* 960ns */, 324300015Sadrian 1); 325300015Sadrian } 326300015Sadrian 327300015Sadrian /* Determine whether ASPM/CLKREQ should be forced on, or forced off. */ 328300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 329300015Sadrian struct bhnd_board_info board; 330300015Sadrian bool aspm_en; 331300015Sadrian 332300015Sadrian /* Fetch board info */ 333300015Sadrian if ((error = bhnd_read_board_info(sc->dev, &board))) 334300015Sadrian return (error); 335300015Sadrian 336300015Sadrian /* Check board flags */ 337300015Sadrian aspm_en = true; 338300015Sadrian if (board.board_flags2 & BHND_BFL2_PCIEWAR_OVR) 339300015Sadrian aspm_en = false; 340300015Sadrian 341300015Sadrian /* Early Apple devices did not (but should have) set 342300015Sadrian * BHND_BFL2_PCIEWAR_OVR in SPROM. */ 343300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN) 344300015Sadrian aspm_en = false; 345300015Sadrian 346300015Sadrian sc->aspm_quirk_override.aspm_en = aspm_en; 347300015Sadrian } 348300015Sadrian 349298479Sadrian /* Determine correct polarity by observing the attach-time PCIe PHY 350298479Sadrian * link status. This is used later to reset/force the SerDes 351298479Sadrian * polarity */ 352298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) { 353298479Sadrian uint32_t st; 354298479Sadrian bool inv; 355298479Sadrian 356298479Sadrian st = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_PLP_STATUSREG); 357298479Sadrian inv = ((st & BHND_PCIE_PLP_POLARITY_INV) != 0); 358298479Sadrian sc->sdr9_quirk_polarity.inv = inv; 359298479Sadrian } 360298479Sadrian 361300015Sadrian /* Override maximum read request size */ 362300015Sadrian if (bhnd_get_class(sc->dev) == BHND_DEVCLASS_PCIE) { 363300015Sadrian int msize; 364300015Sadrian 365300015Sadrian msize = 128; /* compatible with all PCIe-G1 core revisions */ 366300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_DEFAULT_MRRS_512) 367300015Sadrian msize = 512; 368300015Sadrian 369300015Sadrian if (pci_set_max_read_req(sc->pci_dev, msize) == 0) 370300015Sadrian panic("set mrrs on non-PCIe device"); 371300015Sadrian } 372300015Sadrian 373296077Sadrian return (0); 374296077Sadrian} 375296077Sadrian 376298479Sadrian/** 377298479Sadrian * Apply any hardware workarounds that are required upon attach or resume 378298479Sadrian * of the bridge device. 379298479Sadrian */ 380296077Sadrianstatic int 381300015Sadrianbhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state) 382296077Sadrian{ 383298479Sadrian /* Note that the order here matters; these work-arounds 384298479Sadrian * should not be re-ordered without careful review of their 385298479Sadrian * interdependencies */ 386298479Sadrian 387298479Sadrian /* Enable PCI prefetch/burst/readmulti flags */ 388298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST || 389298479Sadrian sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI) 390298479Sadrian { 391298479Sadrian uint32_t sbp2; 392298479Sadrian sbp2 = BHND_PCI_READ_4(sc, BHND_PCI_SBTOPCI2); 393298479Sadrian 394298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST) 395298479Sadrian sbp2 |= (BHND_PCI_SBTOPCI_PREF|BHND_PCI_SBTOPCI_BURST); 396298479Sadrian 397298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI) 398298479Sadrian sbp2 |= BHND_PCI_SBTOPCI_RC_READMULTI; 399298479Sadrian 400298479Sadrian BHND_PCI_WRITE_4(sc, BHND_PCI_SBTOPCI2, sbp2); 401298479Sadrian } 402298479Sadrian 403298479Sadrian /* Disable PCI CLKRUN# */ 404298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_CLKRUN_DSBL) { 405298479Sadrian uint32_t ctl; 406298479Sadrian 407298479Sadrian ctl = BHND_PCI_READ_4(sc, BHND_PCI_CLKRUN_CTL); 408298479Sadrian ctl |= BHND_PCI_CLKRUN_DSBL; 409298479Sadrian BHND_PCI_WRITE_4(sc, BHND_PCI_CLKRUN_CTL, ctl); 410298479Sadrian } 411298479Sadrian 412298479Sadrian /* Enable TLP unmatched address handling work-around */ 413298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_UR_STATUS_FIX) { 414298479Sadrian uint32_t wrs; 415298479Sadrian wrs = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG); 416298479Sadrian wrs |= BHND_PCIE_TLP_WORKAROUND_URBIT; 417298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG, wrs); 418298479Sadrian } 419298479Sadrian 420298479Sadrian /* Adjust SerDes CDR tuning to ensure that CDR is stable before sending 421298479Sadrian * data during L0s to L0 exit transitions. */ 422298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_L0s_HANG) { 423298479Sadrian uint16_t sdv; 424298479Sadrian 425298479Sadrian /* Set RX track/acquire timers to 2.064us/40.96us */ 426298479Sadrian sdv = BPCI_REG_SET(0, PCIE_SDR9_RX_TIMER1_LKTRK, (2064/16)); 427298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_TIMER1_LKACQ, 428298479Sadrian (40960/1024)); 429298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 430298479Sadrian BHND_PCIE_SDR9_RX_TIMER1, sdv); 431298479Sadrian 432298479Sadrian /* Apply CDR frequency workaround */ 433298479Sadrian sdv = BHND_PCIE_SDR9_RX_CDR_FREQ_OVR_EN; 434298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDR_FREQ_OVR, 0x0); 435298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 436298479Sadrian BHND_PCIE_SDR9_RX_CDR, sdv); 437298479Sadrian 438298479Sadrian /* Apply CDR BW tunings */ 439298479Sadrian sdv = 0; 440298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGTRK, 0x2); 441298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGACQ, 0x4); 442298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPTRK, 0x6); 443298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPACQ, 0x6); 444298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 445298479Sadrian BHND_PCIE_SDR9_RX_CDRBW, sdv); 446298479Sadrian } 447298479Sadrian 448298479Sadrian /* Force correct SerDes polarity */ 449298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) { 450298479Sadrian uint16_t rxctl; 451298479Sadrian 452298479Sadrian rxctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_TXRX, 453298479Sadrian BHND_PCIE_SDR9_RX_CTRL); 454298479Sadrian 455298479Sadrian rxctl |= BHND_PCIE_SDR9_RX_CTRL_FORCE; 456298479Sadrian if (sc->sdr9_quirk_polarity.inv) 457298479Sadrian rxctl |= BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV; 458298479Sadrian else 459298479Sadrian rxctl &= ~BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV; 460298479Sadrian 461298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 462298479Sadrian BHND_PCIE_SDR9_RX_CTRL, rxctl); 463298479Sadrian } 464298479Sadrian 465298479Sadrian /* Disable startup retry on PLL frequency detection failure */ 466298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY) { 467298479Sadrian uint16_t pctl; 468298479Sadrian 469298479Sadrian pctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_PLL, 470298479Sadrian BHND_PCIE_SDR9_PLL_CTRL); 471298479Sadrian 472298479Sadrian pctl &= ~BHND_PCIE_SDR9_PLL_CTRL_FREQDET_EN; 473298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_PLL, 474298479Sadrian BHND_PCIE_SDR9_PLL_CTRL, pctl); 475298479Sadrian } 476298479Sadrian 477298479Sadrian /* Explicitly enable PCI-PM */ 478298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_PCIPM_REQEN) { 479298479Sadrian uint32_t lcreg; 480298479Sadrian lcreg = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_LCREG); 481298479Sadrian lcreg |= BHND_PCIE_DLLP_LCREG_PCIPM_EN; 482298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_LCREG, lcreg); 483298479Sadrian } 484298479Sadrian 485298479Sadrian /* Adjust L1 timer to fix slow L1->L0 transitions */ 486298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_L1_IDLE_THRESH) { 487298479Sadrian uint32_t pmt; 488298479Sadrian pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 489298479Sadrian pmt = BPCI_REG_SET(pmt, PCIE_L1THRESHOLDTIME, 490298479Sadrian BHND_PCIE_L1THRESHOLD_WARVAL); 491298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 492298479Sadrian } 493298479Sadrian 494298479Sadrian /* Extend L1 timer for better performance. 495298479Sadrian * TODO: We could enable/disable this on demand for better power 496298479Sadrian * savings if we tie this to HT clock request handling */ 497298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) { 498298479Sadrian uint32_t pmt; 499298479Sadrian pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 500298479Sadrian pmt |= BHND_PCIE_ASPMTIMER_EXTEND; 501298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 502298479Sadrian } 503298479Sadrian 504300015Sadrian /* Override ASPM/ECPM settings in SPROM shadow and PCIER_LINK_CTL */ 505300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 506300015Sadrian bus_size_t reg; 507300015Sadrian uint16_t cfg; 508300015Sadrian 509300015Sadrian /* Set ASPM L1/L0s flags in SPROM shadow */ 510300015Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_ASPM_OFFSET; 511300015Sadrian cfg = BHND_PCI_READ_2(sc, reg); 512300015Sadrian 513300015Sadrian if (sc->aspm_quirk_override.aspm_en) 514300015Sadrian cfg |= BHND_PCIE_SRSH_ASPM_ENB; 515300015Sadrian else 516300015Sadrian cfg &= ~BHND_PCIE_SRSH_ASPM_ENB; 517300015Sadrian 518300015Sadrian BHND_PCI_WRITE_2(sc, reg, cfg); 519300015Sadrian 520300015Sadrian 521300015Sadrian /* Set ASPM/ECPM (CLKREQ) flags in PCIe link control register */ 522300015Sadrian cfg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2); 523300015Sadrian 524300015Sadrian if (sc->aspm_quirk_override.aspm_en) 525300015Sadrian cfg |= PCIEM_LINK_CTL_ASPMC; 526300015Sadrian else 527300015Sadrian cfg &= ~PCIEM_LINK_CTL_ASPMC; 528300015Sadrian 529300015Sadrian cfg &= ~PCIEM_LINK_CTL_ECPM; /* CLKREQ# */ 530300015Sadrian 531300015Sadrian pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, cfg, 2); 532300015Sadrian 533300015Sadrian /* Set CLKREQ (ECPM) flags in SPROM shadow */ 534300015Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_CLKREQ_OFFSET_R5; 535300015Sadrian cfg = BHND_PCI_READ_2(sc, reg); 536300015Sadrian 537300015Sadrian if (sc->aspm_quirk_override.aspm_en) 538300015Sadrian cfg |= BHND_PCIE_SRSH_CLKREQ_ENB; 539300015Sadrian else 540300015Sadrian cfg &= ~BHND_PCIE_SRSH_CLKREQ_ENB; 541300015Sadrian 542300015Sadrian BHND_PCI_WRITE_2(sc, reg, cfg); 543300015Sadrian } 544300015Sadrian 545298479Sadrian /* Enable L23READY_EXIT_NOPRST if not already set in SPROM. */ 546298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET) { 547298479Sadrian bus_size_t reg; 548298479Sadrian uint16_t cfg; 549298479Sadrian 550298479Sadrian /* Fetch the misc cfg flags from SPROM */ 551298479Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_PCIE_MISC_CONFIG; 552298479Sadrian cfg = BHND_PCI_READ_2(sc, reg); 553298479Sadrian 554298479Sadrian /* Write EXIT_NOPRST flag if not already set in SPROM */ 555298479Sadrian if (!(cfg & BHND_PCIE_SRSH_L23READY_EXIT_NOPRST)) { 556298479Sadrian cfg |= BHND_PCIE_SRSH_L23READY_EXIT_NOPRST; 557298479Sadrian BHND_PCI_WRITE_2(sc, reg, cfg); 558298479Sadrian } 559298479Sadrian } 560298479Sadrian 561300015Sadrian /* Disable SerDes PLL down */ 562300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_NOPLLDOWN) { 563300015Sadrian device_t bhnd, chipc; 564300015Sadrian bus_size_t reg; 565300015Sadrian 566300015Sadrian bhnd = device_get_parent(sc->dev); 567300015Sadrian chipc = bhnd_find_child(bhnd, BHND_DEVCLASS_CC, 0); 568300015Sadrian KASSERT(chipc != NULL, ("missing chipcommon device")); 569300015Sadrian 570300015Sadrian /* Write SerDes PLL disable flag to the ChipCommon core */ 571300015Sadrian BHND_CHIPC_WRITE_CHIPCTRL(chipc, CHIPCTRL_4321_PLL_DOWN, 572300015Sadrian CHIPCTRL_4321_PLL_DOWN); 573300015Sadrian 574300015Sadrian /* Clear SPROM shadow backdoor register */ 575300015Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_BD_OFFSET; 576300015Sadrian BHND_PCI_WRITE_2(sc, reg, 0); 577300015Sadrian } 578300015Sadrian 579300015Sadrian /* Adjust TX drive strength and pre-emphasis coefficient */ 580300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST) { 581300015Sadrian uint16_t txdrv; 582300015Sadrian 583300015Sadrian /* Fetch current TX driver parameters */ 584300015Sadrian txdrv = BHND_PCI_MDIO_READ_EXT(sc, BHND_PCIE_PHYADDR_SD, 585300015Sadrian BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER); 586300015Sadrian 587300015Sadrian /* Set 700mV drive strength */ 588300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_700MV) { 589300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF, 590300015Sadrian BHND_PCIE_APPLE_TX_P2_COEFF_700MV); 591300015Sadrian 592300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER, 593300015Sadrian BHND_PCIE_APPLE_TX_IDRIVER_700MV); 594300015Sadrian } 595300015Sadrian 596300015Sadrian /* ... or, set max drive strength */ 597300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_MAX) { 598300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF, 599300015Sadrian BHND_PCIE_APPLE_TX_P2_COEFF_MAX); 600300015Sadrian 601300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER, 602300015Sadrian BHND_PCIE_APPLE_TX_IDRIVER_MAX); 603300015Sadrian } 604300015Sadrian 605300015Sadrian BHND_PCI_MDIO_WRITE_EXT(sc, BHND_PCIE_PHYADDR_SD, 606300015Sadrian BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER, txdrv); 607300015Sadrian } 608300015Sadrian 609296077Sadrian return (0); 610296077Sadrian} 611296077Sadrian 612298479Sadrian/** 613298479Sadrian * Apply any hardware workarounds that are required upon detach or suspend 614298479Sadrian * of the bridge device. 615298479Sadrian */ 616298479Sadrianstatic int 617300015Sadrianbhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state) 618300015Sadrian{ 619298479Sadrian /* Reduce L1 timer for better power savings. 620298479Sadrian * TODO: We could enable/disable this on demand for better power 621298479Sadrian * savings if we tie this to HT clock request handling */ 622298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) { 623298479Sadrian uint32_t pmt; 624298479Sadrian pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 625298479Sadrian pmt &= ~BHND_PCIE_ASPMTIMER_EXTEND; 626298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 627298479Sadrian } 628298479Sadrian 629300015Sadrian /* Enable CLKREQ (ECPM). If suspending, also disable ASPM L1 entry */ 630300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 631300015Sadrian uint16_t lcreg; 632300015Sadrian 633300015Sadrian lcreg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2); 634300015Sadrian 635300015Sadrian lcreg |= PCIEM_LINK_CTL_ECPM; /* CLKREQ# */ 636300015Sadrian if (state == BHND_PCI_WAR_SUSPEND) 637300015Sadrian lcreg &= ~PCIEM_LINK_CTL_ASPMC_L1; 638300015Sadrian 639300015Sadrian pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, lcreg, 2); 640300015Sadrian } 641300015Sadrian 642298479Sadrian return (0); 643298479Sadrian} 644298479Sadrian 645296077Sadrianstatic device_method_t bhnd_pci_hostb_methods[] = { 646296077Sadrian /* Device interface */ 647298479Sadrian DEVMETHOD(device_attach, bhnd_pci_hostb_attach), 648298479Sadrian DEVMETHOD(device_detach, bhnd_pci_hostb_detach), 649298479Sadrian DEVMETHOD(device_suspend, bhnd_pci_hostb_suspend), 650298479Sadrian DEVMETHOD(device_resume, bhnd_pci_hostb_resume), 651296077Sadrian 652296077Sadrian DEVMETHOD_END 653296077Sadrian}; 654296077Sadrian 655300015SadrianDEFINE_CLASS_1(bhnd_hostb, bhnd_pci_hostb_driver, bhnd_pci_hostb_methods, 656298479Sadrian sizeof(struct bhnd_pcihb_softc), bhnd_pci_driver); 657300015SadrianDRIVER_MODULE(bhnd_pci_hostb, bhnd, bhnd_pci_hostb_driver, bhnd_hostb_devclass, 0, 0); 658296077Sadrian 659296077SadrianMODULE_VERSION(bhnd_pci_hostb, 1); 660298947SadrianMODULE_DEPEND(bhnd_pci_hostb, bhnd, 1, 1, 1); 661298479SadrianMODULE_DEPEND(bhnd_pci_hostb, bhnd_pci, 1, 1, 1); 662