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$"); 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[]; 70298479Sadrian 71300015Sadrian/* Device driver work-around variations */ 72300015Sadriantypedef enum { 73300015Sadrian BHND_PCI_WAR_ATTACH, /**< apply attach workarounds */ 74300015Sadrian BHND_PCI_WAR_RESUME, /**< apply resume workarounds */ 75300015Sadrian BHND_PCI_WAR_SUSPEND, /**< apply suspend workarounds */ 76300015Sadrian BHND_PCI_WAR_DETACH /**< apply detach workarounds */ 77300015Sadrian} bhnd_pci_war_state; 78300015Sadrian 79298479Sadrianstatic int bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc); 80300015Sadrianstatic int bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, 81300015Sadrian bhnd_pci_war_state state); 82300015Sadrianstatic int bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, 83300015Sadrian bhnd_pci_war_state state); 84298479Sadrian 85298479Sadrian/* 86298479Sadrian * device/quirk tables 87298479Sadrian */ 88300015Sadrian 89300628Sadrian#define BHND_PCI_DEV(_core, _quirks) \ 90301697Slandonf BHND_DEVICE(BCM, _core, NULL, _quirks, BHND_DF_HOSTB) 91300015Sadrian 92298479Sadrianstatic const struct bhnd_device bhnd_pci_devs[] = { 93300628Sadrian BHND_PCI_DEV(PCI, bhnd_pci_quirks), 94300628Sadrian BHND_PCI_DEV(PCIE, bhnd_pcie_quirks), 95298479Sadrian BHND_DEVICE_END 96296077Sadrian}; 97296077Sadrian 98298479Sadrianstatic const struct bhnd_device_quirk bhnd_pci_quirks[] = { 99300628Sadrian /* core revision quirks */ 100300628Sadrian BHND_CORE_QUIRK (HWREV_ANY, BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST), 101300628Sadrian BHND_CORE_QUIRK (HWREV_GTE(11), BHND_PCI_QUIRK_SBTOPCI2_READMULTI | 102300628Sadrian BHND_PCI_QUIRK_CLKRUN_DSBL), 103298479Sadrian 104300015Sadrian /* BCM4321CB2 boards that require 960ns latency timer override */ 105300628Sadrian BHND_BOARD_QUIRK(BCM4321CB2, BHND_PCI_QUIRK_960NS_LATTIM_OVR), 106300628Sadrian BHND_BOARD_QUIRK(BCM4321CB2_AG, BHND_PCI_QUIRK_960NS_LATTIM_OVR), 107300015Sadrian 108300628Sadrian BHND_DEVICE_QUIRK_END 109300015Sadrian}; 110300015Sadrian 111298479Sadrianstatic const struct bhnd_device_quirk bhnd_pcie_quirks[] = { 112300628Sadrian /* core revision quirks */ 113300628Sadrian BHND_CORE_QUIRK (HWREV_EQ (0), BHND_PCIE_QUIRK_SDR9_L0s_HANG), 114300628Sadrian BHND_CORE_QUIRK (HWREV_RANGE(0,1), 115300628Sadrian BHND_PCIE_QUIRK_UR_STATUS_FIX), 116298479Sadrian 117300628Sadrian BHND_CORE_QUIRK (HWREV_EQ (1), BHND_PCIE_QUIRK_PCIPM_REQEN), 118298479Sadrian 119300628Sadrian BHND_CORE_QUIRK (HWREV_RANGE(3,5), 120300628Sadrian BHND_PCIE_QUIRK_ASPM_OVR | BHND_PCIE_QUIRK_SDR9_POLARITY | 121300628Sadrian BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY), 122300015Sadrian 123300628Sadrian BHND_CORE_QUIRK (HWREV_LTE(6), BHND_PCIE_QUIRK_L1_IDLE_THRESH), 124300628Sadrian BHND_CORE_QUIRK (HWREV_GTE(6), BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET), 125300628Sadrian BHND_CORE_QUIRK (HWREV_EQ (7), BHND_PCIE_QUIRK_SERDES_NOPLLDOWN), 126300628Sadrian BHND_CORE_QUIRK (HWREV_GTE(8), BHND_PCIE_QUIRK_L1_TIMER_PERF), 127300015Sadrian 128300628Sadrian BHND_CORE_QUIRK (HWREV_LTE(17), BHND_PCIE_QUIRK_MAX_MRRS_128), 129298479Sadrian 130299996Sadrian /* Apple boards on which BHND_BFL2_PCIEWAR_OVR should be assumed 131299996Sadrian * to be set. */ 132300628Sadrian {{ BHND_MATCH_BOARD_VENDOR (PCI_VENDOR_APPLE), 133300628Sadrian BHND_MATCH_BOARD_REV (HWREV_LTE(0x71)), 134300628Sadrian BHND_MATCH_SROMREV (EQ(4)) }, 135300628Sadrian BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN }, 136299996Sadrian 137300015Sadrian /* Apple BCM4322 boards that require 700mV SerDes TX drive strength. */ 138300628Sadrian {{ BHND_CHIP_ID(BCM4322), 139300628Sadrian BHND_MATCH_BOARD(PCI_VENDOR_APPLE, BCM94322X9), }, 140300628Sadrian BHND_PCIE_QUIRK_SERDES_TXDRV_700MV }, 141300015Sadrian 142300015Sadrian /* Apple BCM4331 board-specific quirks */ 143300628Sadrian#define BHND_A4331_QUIRK(_board, ...) \ 144300628Sadrian {{ BHND_CHIP_ID(BCM4331), \ 145300628Sadrian BHND_MATCH_BOARD(PCI_VENDOR_APPLE, _board) }, __VA_ARGS__ } 146300015Sadrian 147300628Sadrian BHND_A4331_QUIRK(BCM94331X19, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 148300628Sadrian BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 149300015Sadrian 150300628Sadrian BHND_A4331_QUIRK(BCM94331X28, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 151300628Sadrian BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 152300015Sadrian 153300628Sadrian BHND_A4331_QUIRK(BCM94331X28B, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 154300628Sadrian 155300628Sadrian BHND_A4331_QUIRK(BCM94331X29B, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 156300628Sadrian BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 157300628Sadrian 158300628Sadrian BHND_A4331_QUIRK(BCM94331X19C, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 159300628Sadrian BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 160300015Sadrian 161300628Sadrian BHND_A4331_QUIRK(BCM94331X29D, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 162300015Sadrian 163300628Sadrian BHND_A4331_QUIRK(BCM94331X33, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 164300628Sadrian 165300628Sadrian#undef BHND_A4331_QUIRK 166300628Sadrian 167300628Sadrian BHND_DEVICE_QUIRK_END 168299996Sadrian}; 169299996Sadrian 170300628Sadrian 171298479Sadrian#define BHND_PCI_SOFTC(_sc) (&((_sc)->common)) 172298479Sadrian 173298479Sadrian#define BHND_PCI_READ_2(_sc, _reg) \ 174298479Sadrian bhnd_bus_read_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg)) 175298479Sadrian 176298479Sadrian#define BHND_PCI_READ_4(_sc, _reg) \ 177298479Sadrian bhnd_bus_read_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg)) 178298479Sadrian 179298479Sadrian#define BHND_PCI_WRITE_2(_sc, _reg, _val) \ 180298479Sadrian bhnd_bus_write_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val)) 181298479Sadrian 182298479Sadrian#define BHND_PCI_WRITE_4(_sc, _reg, _val) \ 183298479Sadrian bhnd_bus_write_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val)) 184298479Sadrian 185298479Sadrian#define BHND_PCI_PROTO_READ_4(_sc, _reg) \ 186298479Sadrian bhnd_pcie_read_proto_reg(BHND_PCI_SOFTC(_sc), (_reg)) 187298479Sadrian 188298479Sadrian#define BHND_PCI_PROTO_WRITE_4(_sc, _reg, _val) \ 189298479Sadrian bhnd_pcie_write_proto_reg(BHND_PCI_SOFTC(_sc), (_reg), (_val)) 190298479Sadrian 191298479Sadrian#define BHND_PCI_MDIO_READ(_sc, _phy, _reg) \ 192298479Sadrian bhnd_pcie_mdio_read(BHND_PCI_SOFTC(_sc), (_phy), (_reg)) 193298479Sadrian 194298479Sadrian#define BHND_PCI_MDIO_WRITE(_sc, _phy, _reg, _val) \ 195298479Sadrian bhnd_pcie_mdio_write(BHND_PCI_SOFTC(_sc), (_phy), (_reg), (_val)) 196298479Sadrian 197300015Sadrian#define BHND_PCI_MDIO_READ_EXT(_sc, _phy, _devaddr, _reg) \ 198300015Sadrian bhnd_pcie_mdio_read_ext(BHND_PCI_SOFTC(_sc), (_phy), (_devaddr), (_reg)) 199300015Sadrian 200300015Sadrian#define BHND_PCI_MDIO_WRITE_EXT(_sc, _phy, _devaddr, _reg, _val) \ 201300015Sadrian bhnd_pcie_mdio_write_ext(BHND_PCI_SOFTC(_sc), (_phy), \ 202300015Sadrian (_devaddr), (_reg), (_val)) 203300015Sadrian 204298479Sadrian#define BPCI_REG_SET(_regv, _attr, _val) \ 205298479Sadrian BHND_PCI_REG_SET((_regv), BHND_ ## _attr, (_val)) 206298479Sadrian 207298479Sadrian#define BPCI_REG_GET(_regv, _attr) \ 208298479Sadrian BHND_PCI_REG_GET((_regv), BHND_ ## _attr) 209298479Sadrian 210298479Sadrian#define BPCI_CMN_REG_SET(_regv, _attr, _val) \ 211298479Sadrian BHND_PCI_CMN_REG_SET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv), \ 212298479Sadrian BHND_ ## _attr, (_val)) 213298479Sadrian 214298479Sadrian#define BPCI_CMN_REG_GET(_regv, _attr) \ 215298479Sadrian BHND_PCI_CMN_REG_GET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv), \ 216298479Sadrian BHND_ ## _attr) 217298479Sadrian 218296077Sadrianstatic int 219298479Sadrianbhnd_pci_hostb_attach(device_t dev) 220296077Sadrian{ 221298479Sadrian struct bhnd_pcihb_softc *sc; 222298479Sadrian int error; 223298479Sadrian 224298479Sadrian sc = device_get_softc(dev); 225300015Sadrian sc->dev = dev; 226298479Sadrian sc->quirks = bhnd_device_quirks(dev, bhnd_pci_devs, 227298479Sadrian sizeof(bhnd_pci_devs[0])); 228298479Sadrian 229300015Sadrian /* Find the host PCI bridge device */ 230300015Sadrian sc->pci_dev = bhnd_find_bridge_root(dev, devclass_find("pci")); 231300015Sadrian if (sc->pci_dev == NULL) { 232300015Sadrian device_printf(dev, "parent pci bridge device not found\n"); 233300015Sadrian return (ENXIO); 234300015Sadrian } 235300015Sadrian 236300015Sadrian /* Common setup */ 237298479Sadrian if ((error = bhnd_pci_generic_attach(dev))) 238298479Sadrian return (error); 239298479Sadrian 240298479Sadrian /* Apply early single-shot work-arounds */ 241300015Sadrian if ((error = bhnd_pci_wars_early_once(sc))) 242300015Sadrian goto failed; 243296077Sadrian 244298479Sadrian /* Apply attach/resume work-arounds */ 245300015Sadrian if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_ATTACH))) 246300015Sadrian goto failed; 247296077Sadrian 248298479Sadrian return (0); 249300015Sadrian 250300015Sadrianfailed: 251300015Sadrian bhnd_pci_generic_detach(dev); 252300015Sadrian return (error); 253296077Sadrian} 254296077Sadrian 255296077Sadrianstatic int 256298479Sadrianbhnd_pci_hostb_detach(device_t dev) 257296077Sadrian{ 258298479Sadrian struct bhnd_pcihb_softc *sc; 259298479Sadrian int error; 260298479Sadrian 261298479Sadrian sc = device_get_softc(dev); 262298479Sadrian 263298479Sadrian /* Apply suspend/detach work-arounds */ 264300015Sadrian if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_DETACH))) 265298479Sadrian return (error); 266298479Sadrian 267298479Sadrian return (bhnd_pci_generic_detach(dev)); 268296077Sadrian} 269296077Sadrian 270296077Sadrianstatic int 271298479Sadrianbhnd_pci_hostb_suspend(device_t dev) 272296077Sadrian{ 273298479Sadrian struct bhnd_pcihb_softc *sc; 274298479Sadrian int error; 275298479Sadrian 276298479Sadrian sc = device_get_softc(dev); 277298479Sadrian 278298479Sadrian /* Apply suspend/detach work-arounds */ 279300015Sadrian if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_SUSPEND))) 280298479Sadrian return (error); 281298479Sadrian 282298479Sadrian return (bhnd_pci_generic_suspend(dev)); 283298479Sadrian} 284298479Sadrian 285298479Sadrianstatic int 286298479Sadrianbhnd_pci_hostb_resume(device_t dev) 287298479Sadrian{ 288298479Sadrian struct bhnd_pcihb_softc *sc; 289298479Sadrian int error; 290298479Sadrian 291298479Sadrian sc = device_get_softc(dev); 292298479Sadrian 293298479Sadrian if ((error = bhnd_pci_generic_resume(dev))) 294298479Sadrian return (error); 295298479Sadrian 296298479Sadrian /* Apply attach/resume work-arounds */ 297300015Sadrian if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_RESUME))) { 298298479Sadrian bhnd_pci_generic_detach(dev); 299298479Sadrian return (error); 300298479Sadrian } 301298479Sadrian 302296077Sadrian return (0); 303296077Sadrian} 304296077Sadrian 305298479Sadrian/** 306298479Sadrian * Apply any hardware work-arounds that must be executed exactly once, early in 307298479Sadrian * the attach process. 308298479Sadrian * 309298479Sadrian * This must be called after core enumeration and discovery of all applicable 310298479Sadrian * quirks, but prior to probe/attach of any cores, parsing of 311298479Sadrian * SPROM, etc. 312298479Sadrian */ 313296077Sadrianstatic int 314298479Sadrianbhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc) 315296077Sadrian{ 316300015Sadrian int error; 317300015Sadrian 318300015Sadrian /* Set PCI latency timer */ 319300015Sadrian if (sc->quirks & BHND_PCI_QUIRK_960NS_LATTIM_OVR) { 320300015Sadrian pci_write_config(sc->pci_dev, PCIR_LATTIMER, 0x20 /* 960ns */, 321300015Sadrian 1); 322300015Sadrian } 323300015Sadrian 324300015Sadrian /* Determine whether ASPM/CLKREQ should be forced on, or forced off. */ 325300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 326300015Sadrian struct bhnd_board_info board; 327300015Sadrian bool aspm_en; 328300015Sadrian 329300015Sadrian /* Fetch board info */ 330300015Sadrian if ((error = bhnd_read_board_info(sc->dev, &board))) 331300015Sadrian return (error); 332300015Sadrian 333300015Sadrian /* Check board flags */ 334300015Sadrian aspm_en = true; 335300015Sadrian if (board.board_flags2 & BHND_BFL2_PCIEWAR_OVR) 336300015Sadrian aspm_en = false; 337300015Sadrian 338300015Sadrian /* Early Apple devices did not (but should have) set 339300015Sadrian * BHND_BFL2_PCIEWAR_OVR in SPROM. */ 340300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN) 341300015Sadrian aspm_en = false; 342300015Sadrian 343300015Sadrian sc->aspm_quirk_override.aspm_en = aspm_en; 344300015Sadrian } 345300015Sadrian 346298479Sadrian /* Determine correct polarity by observing the attach-time PCIe PHY 347298479Sadrian * link status. This is used later to reset/force the SerDes 348298479Sadrian * polarity */ 349298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) { 350298479Sadrian uint32_t st; 351298479Sadrian bool inv; 352298479Sadrian 353298479Sadrian st = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_PLP_STATUSREG); 354298479Sadrian inv = ((st & BHND_PCIE_PLP_POLARITY_INV) != 0); 355298479Sadrian sc->sdr9_quirk_polarity.inv = inv; 356298479Sadrian } 357298479Sadrian 358300015Sadrian /* Override maximum read request size */ 359300015Sadrian if (bhnd_get_class(sc->dev) == BHND_DEVCLASS_PCIE) { 360300015Sadrian int msize; 361300015Sadrian 362300015Sadrian msize = 128; /* compatible with all PCIe-G1 core revisions */ 363300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_DEFAULT_MRRS_512) 364300015Sadrian msize = 512; 365300015Sadrian 366300015Sadrian if (pci_set_max_read_req(sc->pci_dev, msize) == 0) 367300015Sadrian panic("set mrrs on non-PCIe device"); 368300015Sadrian } 369300015Sadrian 370296077Sadrian return (0); 371296077Sadrian} 372296077Sadrian 373298479Sadrian/** 374298479Sadrian * Apply any hardware workarounds that are required upon attach or resume 375298479Sadrian * of the bridge device. 376298479Sadrian */ 377296077Sadrianstatic int 378300015Sadrianbhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state) 379296077Sadrian{ 380298479Sadrian /* Note that the order here matters; these work-arounds 381298479Sadrian * should not be re-ordered without careful review of their 382298479Sadrian * interdependencies */ 383298479Sadrian 384298479Sadrian /* Enable PCI prefetch/burst/readmulti flags */ 385298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST || 386298479Sadrian sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI) 387298479Sadrian { 388298479Sadrian uint32_t sbp2; 389298479Sadrian sbp2 = BHND_PCI_READ_4(sc, BHND_PCI_SBTOPCI2); 390298479Sadrian 391298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST) 392298479Sadrian sbp2 |= (BHND_PCI_SBTOPCI_PREF|BHND_PCI_SBTOPCI_BURST); 393298479Sadrian 394298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI) 395298479Sadrian sbp2 |= BHND_PCI_SBTOPCI_RC_READMULTI; 396298479Sadrian 397298479Sadrian BHND_PCI_WRITE_4(sc, BHND_PCI_SBTOPCI2, sbp2); 398298479Sadrian } 399298479Sadrian 400298479Sadrian /* Disable PCI CLKRUN# */ 401298479Sadrian if (sc->quirks & BHND_PCI_QUIRK_CLKRUN_DSBL) { 402298479Sadrian uint32_t ctl; 403298479Sadrian 404298479Sadrian ctl = BHND_PCI_READ_4(sc, BHND_PCI_CLKRUN_CTL); 405298479Sadrian ctl |= BHND_PCI_CLKRUN_DSBL; 406298479Sadrian BHND_PCI_WRITE_4(sc, BHND_PCI_CLKRUN_CTL, ctl); 407298479Sadrian } 408298479Sadrian 409298479Sadrian /* Enable TLP unmatched address handling work-around */ 410298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_UR_STATUS_FIX) { 411298479Sadrian uint32_t wrs; 412298479Sadrian wrs = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG); 413298479Sadrian wrs |= BHND_PCIE_TLP_WORKAROUND_URBIT; 414298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG, wrs); 415298479Sadrian } 416298479Sadrian 417298479Sadrian /* Adjust SerDes CDR tuning to ensure that CDR is stable before sending 418298479Sadrian * data during L0s to L0 exit transitions. */ 419298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_L0s_HANG) { 420298479Sadrian uint16_t sdv; 421298479Sadrian 422298479Sadrian /* Set RX track/acquire timers to 2.064us/40.96us */ 423298479Sadrian sdv = BPCI_REG_SET(0, PCIE_SDR9_RX_TIMER1_LKTRK, (2064/16)); 424298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_TIMER1_LKACQ, 425298479Sadrian (40960/1024)); 426298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 427298479Sadrian BHND_PCIE_SDR9_RX_TIMER1, sdv); 428298479Sadrian 429298479Sadrian /* Apply CDR frequency workaround */ 430298479Sadrian sdv = BHND_PCIE_SDR9_RX_CDR_FREQ_OVR_EN; 431298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDR_FREQ_OVR, 0x0); 432298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 433298479Sadrian BHND_PCIE_SDR9_RX_CDR, sdv); 434298479Sadrian 435298479Sadrian /* Apply CDR BW tunings */ 436298479Sadrian sdv = 0; 437298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGTRK, 0x2); 438298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGACQ, 0x4); 439298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPTRK, 0x6); 440298479Sadrian sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPACQ, 0x6); 441298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 442298479Sadrian BHND_PCIE_SDR9_RX_CDRBW, sdv); 443298479Sadrian } 444298479Sadrian 445298479Sadrian /* Force correct SerDes polarity */ 446298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) { 447298479Sadrian uint16_t rxctl; 448298479Sadrian 449298479Sadrian rxctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_TXRX, 450298479Sadrian BHND_PCIE_SDR9_RX_CTRL); 451298479Sadrian 452298479Sadrian rxctl |= BHND_PCIE_SDR9_RX_CTRL_FORCE; 453298479Sadrian if (sc->sdr9_quirk_polarity.inv) 454298479Sadrian rxctl |= BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV; 455298479Sadrian else 456298479Sadrian rxctl &= ~BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV; 457298479Sadrian 458298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 459298479Sadrian BHND_PCIE_SDR9_RX_CTRL, rxctl); 460298479Sadrian } 461298479Sadrian 462298479Sadrian /* Disable startup retry on PLL frequency detection failure */ 463298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY) { 464298479Sadrian uint16_t pctl; 465298479Sadrian 466298479Sadrian pctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_PLL, 467298479Sadrian BHND_PCIE_SDR9_PLL_CTRL); 468298479Sadrian 469298479Sadrian pctl &= ~BHND_PCIE_SDR9_PLL_CTRL_FREQDET_EN; 470298479Sadrian BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_PLL, 471298479Sadrian BHND_PCIE_SDR9_PLL_CTRL, pctl); 472298479Sadrian } 473298479Sadrian 474298479Sadrian /* Explicitly enable PCI-PM */ 475298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_PCIPM_REQEN) { 476298479Sadrian uint32_t lcreg; 477298479Sadrian lcreg = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_LCREG); 478298479Sadrian lcreg |= BHND_PCIE_DLLP_LCREG_PCIPM_EN; 479298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_LCREG, lcreg); 480298479Sadrian } 481298479Sadrian 482298479Sadrian /* Adjust L1 timer to fix slow L1->L0 transitions */ 483298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_L1_IDLE_THRESH) { 484298479Sadrian uint32_t pmt; 485298479Sadrian pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 486298479Sadrian pmt = BPCI_REG_SET(pmt, PCIE_L1THRESHOLDTIME, 487298479Sadrian BHND_PCIE_L1THRESHOLD_WARVAL); 488298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 489298479Sadrian } 490298479Sadrian 491298479Sadrian /* Extend L1 timer for better performance. 492298479Sadrian * TODO: We could enable/disable this on demand for better power 493298479Sadrian * savings if we tie this to HT clock request handling */ 494298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) { 495298479Sadrian uint32_t pmt; 496298479Sadrian pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 497298479Sadrian pmt |= BHND_PCIE_ASPMTIMER_EXTEND; 498298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 499298479Sadrian } 500298479Sadrian 501300015Sadrian /* Override ASPM/ECPM settings in SPROM shadow and PCIER_LINK_CTL */ 502300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 503300015Sadrian bus_size_t reg; 504300015Sadrian uint16_t cfg; 505300015Sadrian 506300015Sadrian /* Set ASPM L1/L0s flags in SPROM shadow */ 507300015Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_ASPM_OFFSET; 508300015Sadrian cfg = BHND_PCI_READ_2(sc, reg); 509300015Sadrian 510300015Sadrian if (sc->aspm_quirk_override.aspm_en) 511300015Sadrian cfg |= BHND_PCIE_SRSH_ASPM_ENB; 512300015Sadrian else 513300015Sadrian cfg &= ~BHND_PCIE_SRSH_ASPM_ENB; 514300015Sadrian 515300015Sadrian BHND_PCI_WRITE_2(sc, reg, cfg); 516300015Sadrian 517300015Sadrian 518300015Sadrian /* Set ASPM/ECPM (CLKREQ) flags in PCIe link control register */ 519300015Sadrian cfg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2); 520300015Sadrian 521300015Sadrian if (sc->aspm_quirk_override.aspm_en) 522300015Sadrian cfg |= PCIEM_LINK_CTL_ASPMC; 523300015Sadrian else 524300015Sadrian cfg &= ~PCIEM_LINK_CTL_ASPMC; 525300015Sadrian 526300015Sadrian cfg &= ~PCIEM_LINK_CTL_ECPM; /* CLKREQ# */ 527300015Sadrian 528300015Sadrian pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, cfg, 2); 529300015Sadrian 530300015Sadrian /* Set CLKREQ (ECPM) flags in SPROM shadow */ 531300015Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_CLKREQ_OFFSET_R5; 532300015Sadrian cfg = BHND_PCI_READ_2(sc, reg); 533300015Sadrian 534300015Sadrian if (sc->aspm_quirk_override.aspm_en) 535300015Sadrian cfg |= BHND_PCIE_SRSH_CLKREQ_ENB; 536300015Sadrian else 537300015Sadrian cfg &= ~BHND_PCIE_SRSH_CLKREQ_ENB; 538300015Sadrian 539300015Sadrian BHND_PCI_WRITE_2(sc, reg, cfg); 540300015Sadrian } 541300015Sadrian 542298479Sadrian /* Enable L23READY_EXIT_NOPRST if not already set in SPROM. */ 543298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET) { 544298479Sadrian bus_size_t reg; 545298479Sadrian uint16_t cfg; 546298479Sadrian 547298479Sadrian /* Fetch the misc cfg flags from SPROM */ 548298479Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_PCIE_MISC_CONFIG; 549298479Sadrian cfg = BHND_PCI_READ_2(sc, reg); 550298479Sadrian 551298479Sadrian /* Write EXIT_NOPRST flag if not already set in SPROM */ 552298479Sadrian if (!(cfg & BHND_PCIE_SRSH_L23READY_EXIT_NOPRST)) { 553298479Sadrian cfg |= BHND_PCIE_SRSH_L23READY_EXIT_NOPRST; 554298479Sadrian BHND_PCI_WRITE_2(sc, reg, cfg); 555298479Sadrian } 556298479Sadrian } 557298479Sadrian 558300015Sadrian /* Disable SerDes PLL down */ 559300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_NOPLLDOWN) { 560300015Sadrian device_t bhnd, chipc; 561300015Sadrian bus_size_t reg; 562300015Sadrian 563300015Sadrian bhnd = device_get_parent(sc->dev); 564300015Sadrian chipc = bhnd_find_child(bhnd, BHND_DEVCLASS_CC, 0); 565300015Sadrian KASSERT(chipc != NULL, ("missing chipcommon device")); 566300015Sadrian 567300015Sadrian /* Write SerDes PLL disable flag to the ChipCommon core */ 568300015Sadrian BHND_CHIPC_WRITE_CHIPCTRL(chipc, CHIPCTRL_4321_PLL_DOWN, 569300015Sadrian CHIPCTRL_4321_PLL_DOWN); 570300015Sadrian 571300015Sadrian /* Clear SPROM shadow backdoor register */ 572300015Sadrian reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_BD_OFFSET; 573300015Sadrian BHND_PCI_WRITE_2(sc, reg, 0); 574300015Sadrian } 575300015Sadrian 576300015Sadrian /* Adjust TX drive strength and pre-emphasis coefficient */ 577300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST) { 578300015Sadrian uint16_t txdrv; 579300015Sadrian 580300015Sadrian /* Fetch current TX driver parameters */ 581300015Sadrian txdrv = BHND_PCI_MDIO_READ_EXT(sc, BHND_PCIE_PHYADDR_SD, 582300015Sadrian BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER); 583300015Sadrian 584300015Sadrian /* Set 700mV drive strength */ 585300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_700MV) { 586300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF, 587300015Sadrian BHND_PCIE_APPLE_TX_P2_COEFF_700MV); 588300015Sadrian 589300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER, 590300015Sadrian BHND_PCIE_APPLE_TX_IDRIVER_700MV); 591300015Sadrian } 592300015Sadrian 593300015Sadrian /* ... or, set max drive strength */ 594300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_MAX) { 595300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF, 596300015Sadrian BHND_PCIE_APPLE_TX_P2_COEFF_MAX); 597300015Sadrian 598300015Sadrian txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER, 599300015Sadrian BHND_PCIE_APPLE_TX_IDRIVER_MAX); 600300015Sadrian } 601300015Sadrian 602300015Sadrian BHND_PCI_MDIO_WRITE_EXT(sc, BHND_PCIE_PHYADDR_SD, 603300015Sadrian BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER, txdrv); 604300015Sadrian } 605300015Sadrian 606296077Sadrian return (0); 607296077Sadrian} 608296077Sadrian 609298479Sadrian/** 610298479Sadrian * Apply any hardware workarounds that are required upon detach or suspend 611298479Sadrian * of the bridge device. 612298479Sadrian */ 613298479Sadrianstatic int 614300015Sadrianbhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state) 615300015Sadrian{ 616298479Sadrian /* Reduce L1 timer for better power savings. 617298479Sadrian * TODO: We could enable/disable this on demand for better power 618298479Sadrian * savings if we tie this to HT clock request handling */ 619298479Sadrian if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) { 620298479Sadrian uint32_t pmt; 621298479Sadrian pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 622298479Sadrian pmt &= ~BHND_PCIE_ASPMTIMER_EXTEND; 623298479Sadrian BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 624298479Sadrian } 625298479Sadrian 626300015Sadrian /* Enable CLKREQ (ECPM). If suspending, also disable ASPM L1 entry */ 627300015Sadrian if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 628300015Sadrian uint16_t lcreg; 629300015Sadrian 630300015Sadrian lcreg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2); 631300015Sadrian 632300015Sadrian lcreg |= PCIEM_LINK_CTL_ECPM; /* CLKREQ# */ 633300015Sadrian if (state == BHND_PCI_WAR_SUSPEND) 634300015Sadrian lcreg &= ~PCIEM_LINK_CTL_ASPMC_L1; 635300015Sadrian 636300015Sadrian pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, lcreg, 2); 637300015Sadrian } 638300015Sadrian 639298479Sadrian return (0); 640298479Sadrian} 641298479Sadrian 642296077Sadrianstatic device_method_t bhnd_pci_hostb_methods[] = { 643296077Sadrian /* Device interface */ 644298479Sadrian DEVMETHOD(device_attach, bhnd_pci_hostb_attach), 645298479Sadrian DEVMETHOD(device_detach, bhnd_pci_hostb_detach), 646298479Sadrian DEVMETHOD(device_suspend, bhnd_pci_hostb_suspend), 647298479Sadrian DEVMETHOD(device_resume, bhnd_pci_hostb_resume), 648296077Sadrian 649296077Sadrian DEVMETHOD_END 650296077Sadrian}; 651296077Sadrian 652300015SadrianDEFINE_CLASS_1(bhnd_hostb, bhnd_pci_hostb_driver, bhnd_pci_hostb_methods, 653298479Sadrian sizeof(struct bhnd_pcihb_softc), bhnd_pci_driver); 654300015SadrianDRIVER_MODULE(bhnd_pci_hostb, bhnd, bhnd_pci_hostb_driver, bhnd_hostb_devclass, 0, 0); 655296077Sadrian 656296077SadrianMODULE_VERSION(bhnd_pci_hostb, 1); 657298947SadrianMODULE_DEPEND(bhnd_pci_hostb, bhnd, 1, 1, 1); 658298479SadrianMODULE_DEPEND(bhnd_pci_hostb, bhnd_pci, 1, 1, 1); 659