1 /*- 2 * Copyright (c) 2015-2016 Landon Fuller <landon@landonf.org> 3 * Copyright (c) 2017 The FreeBSD Foundation 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Landon Fuller 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer, 14 * without modification. 15 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 16 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 17 * redistribution must be conditioned upon including a substantially 18 * similar Disclaimer requirement for further binary redistribution. 19 * 20 * NO WARRANTY 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 24 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 25 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 26 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 29 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 * THE POSSIBILITY OF SUCH DAMAGES. 32 */ 33 34 #include <sys/cdefs.h> 35 __FBSDID("$FreeBSD$"); 36 37 /* 38 * Broadcom BHND PCI/PCIe-Gen1 PCI-Host Bridge. 39 * 40 * This driver handles all interactions with PCI bridge cores operating in 41 * endpoint mode. 42 * 43 * Host-level PCI operations are handled at the bhndb bridge level by the 44 * bhndb_pci driver. 45 */ 46 47 #include <sys/param.h> 48 #include <sys/kernel.h> 49 50 #include <sys/malloc.h> 51 52 #include <sys/bus.h> 53 #include <sys/module.h> 54 55 #include <sys/systm.h> 56 57 #include <machine/bus.h> 58 #include <sys/rman.h> 59 #include <machine/resource.h> 60 61 #include <dev/bhnd/bhnd.h> 62 63 #include <dev/pci/pcireg.h> 64 #include <dev/pci/pcivar.h> 65 66 #include <dev/bhnd/cores/chipc/chipc.h> 67 #include <dev/bhnd/cores/chipc/chipcreg.h> 68 69 #include "bhnd_pcireg.h" 70 #include "bhnd_pci_hostbvar.h" 71 72 static const struct bhnd_device_quirk bhnd_pci_quirks[]; 73 static const struct bhnd_device_quirk bhnd_pcie_quirks[]; 74 75 /* Device driver work-around variations */ 76 typedef enum { 77 BHND_PCI_WAR_ATTACH, /**< apply attach workarounds */ 78 BHND_PCI_WAR_RESUME, /**< apply resume workarounds */ 79 BHND_PCI_WAR_SUSPEND, /**< apply suspend workarounds */ 80 BHND_PCI_WAR_DETACH /**< apply detach workarounds */ 81 } bhnd_pci_war_state; 82 83 static int bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc); 84 static int bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, 85 bhnd_pci_war_state state); 86 static int bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, 87 bhnd_pci_war_state state); 88 89 /* 90 * device/quirk tables 91 */ 92 93 #define BHND_PCI_DEV(_core, _quirks) \ 94 BHND_DEVICE(BCM, _core, NULL, _quirks, BHND_DF_HOSTB) 95 96 static const struct bhnd_device bhnd_pci_devs[] = { 97 BHND_PCI_DEV(PCI, bhnd_pci_quirks), 98 BHND_PCI_DEV(PCIE, bhnd_pcie_quirks), 99 BHND_DEVICE_END 100 }; 101 102 static const struct bhnd_device_quirk bhnd_pci_quirks[] = { 103 /* core revision quirks */ 104 BHND_CORE_QUIRK (HWREV_ANY, BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST), 105 BHND_CORE_QUIRK (HWREV_GTE(11), BHND_PCI_QUIRK_SBTOPCI2_READMULTI | 106 BHND_PCI_QUIRK_CLKRUN_DSBL), 107 108 /* BCM4321CB2 boards that require 960ns latency timer override */ 109 BHND_BOARD_QUIRK(BCM4321CB2, BHND_PCI_QUIRK_960NS_LATTIM_OVR), 110 BHND_BOARD_QUIRK(BCM4321CB2_AG, BHND_PCI_QUIRK_960NS_LATTIM_OVR), 111 112 BHND_DEVICE_QUIRK_END 113 }; 114 115 static const struct bhnd_device_quirk bhnd_pcie_quirks[] = { 116 /* core revision quirks */ 117 BHND_CORE_QUIRK (HWREV_EQ (0), BHND_PCIE_QUIRK_SDR9_L0s_HANG), 118 BHND_CORE_QUIRK (HWREV_RANGE(0,1), 119 BHND_PCIE_QUIRK_UR_STATUS_FIX), 120 121 BHND_CORE_QUIRK (HWREV_EQ (1), BHND_PCIE_QUIRK_PCIPM_REQEN), 122 123 BHND_CORE_QUIRK (HWREV_RANGE(3,5), 124 BHND_PCIE_QUIRK_ASPM_OVR | BHND_PCIE_QUIRK_SDR9_POLARITY | 125 BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY), 126 127 BHND_CORE_QUIRK (HWREV_LTE(6), BHND_PCIE_QUIRK_L1_IDLE_THRESH), 128 BHND_CORE_QUIRK (HWREV_GTE(6), BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET), 129 BHND_CORE_QUIRK (HWREV_EQ (7), BHND_PCIE_QUIRK_SERDES_NOPLLDOWN), 130 BHND_CORE_QUIRK (HWREV_GTE(8), BHND_PCIE_QUIRK_L1_TIMER_PERF), 131 132 BHND_CORE_QUIRK (HWREV_LTE(17), BHND_PCIE_QUIRK_MAX_MRRS_128), 133 134 /* Apple boards on which BHND_BFL2_PCIEWAR_OVR should be assumed 135 * to be set. */ 136 {{ BHND_MATCH_BOARD_VENDOR (PCI_VENDOR_APPLE), 137 BHND_MATCH_BOARD_REV (HWREV_LTE(0x71)), 138 BHND_MATCH_SROMREV (EQ(4)) }, 139 BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN }, 140 141 /* Apple BCM4322 boards that require 700mV SerDes TX drive strength. */ 142 {{ BHND_MATCH_CHIP_ID(BCM4322), 143 BHND_MATCH_BOARD(PCI_VENDOR_APPLE, BCM94322X9), }, 144 BHND_PCIE_QUIRK_SERDES_TXDRV_700MV }, 145 146 /* Apple BCM4331 board-specific quirks */ 147 #define BHND_A4331_QUIRK(_board, ...) \ 148 {{ BHND_MATCH_CHIP_ID(BCM4331), \ 149 BHND_MATCH_BOARD(PCI_VENDOR_APPLE, _board) }, __VA_ARGS__ } 150 151 BHND_A4331_QUIRK(BCM94331X19, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 152 BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 153 154 BHND_A4331_QUIRK(BCM94331X28, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 155 BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 156 157 BHND_A4331_QUIRK(BCM94331X28B, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 158 159 BHND_A4331_QUIRK(BCM94331X29B, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 160 BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 161 162 BHND_A4331_QUIRK(BCM94331X19C, BHND_PCIE_QUIRK_SERDES_TXDRV_MAX | 163 BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 164 165 BHND_A4331_QUIRK(BCM94331X29D, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 166 167 BHND_A4331_QUIRK(BCM94331X33, BHND_PCIE_QUIRK_DEFAULT_MRRS_512), 168 169 #undef BHND_A4331_QUIRK 170 171 BHND_DEVICE_QUIRK_END 172 }; 173 174 175 #define BHND_PCI_SOFTC(_sc) (&((_sc)->common)) 176 177 #define BHND_PCI_READ_2(_sc, _reg) \ 178 bhnd_bus_read_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg)) 179 180 #define BHND_PCI_READ_4(_sc, _reg) \ 181 bhnd_bus_read_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg)) 182 183 #define BHND_PCI_WRITE_2(_sc, _reg, _val) \ 184 bhnd_bus_write_2(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val)) 185 186 #define BHND_PCI_WRITE_4(_sc, _reg, _val) \ 187 bhnd_bus_write_4(BHND_PCI_SOFTC(_sc)->mem_res, (_reg), (_val)) 188 189 #define BHND_PCI_PROTO_READ_4(_sc, _reg) \ 190 bhnd_pcie_read_proto_reg(BHND_PCI_SOFTC(_sc), (_reg)) 191 192 #define BHND_PCI_PROTO_WRITE_4(_sc, _reg, _val) \ 193 bhnd_pcie_write_proto_reg(BHND_PCI_SOFTC(_sc), (_reg), (_val)) 194 195 #define BHND_PCI_MDIO_READ(_sc, _phy, _reg) \ 196 bhnd_pcie_mdio_read(BHND_PCI_SOFTC(_sc), (_phy), (_reg)) 197 198 #define BHND_PCI_MDIO_WRITE(_sc, _phy, _reg, _val) \ 199 bhnd_pcie_mdio_write(BHND_PCI_SOFTC(_sc), (_phy), (_reg), (_val)) 200 201 #define BHND_PCI_MDIO_READ_EXT(_sc, _phy, _devaddr, _reg) \ 202 bhnd_pcie_mdio_read_ext(BHND_PCI_SOFTC(_sc), (_phy), (_devaddr), (_reg)) 203 204 #define BHND_PCI_MDIO_WRITE_EXT(_sc, _phy, _devaddr, _reg, _val) \ 205 bhnd_pcie_mdio_write_ext(BHND_PCI_SOFTC(_sc), (_phy), \ 206 (_devaddr), (_reg), (_val)) 207 208 #define BPCI_REG_SET(_regv, _attr, _val) \ 209 BHND_PCI_REG_SET((_regv), BHND_ ## _attr, (_val)) 210 211 #define BPCI_REG_GET(_regv, _attr) \ 212 BHND_PCI_REG_GET((_regv), BHND_ ## _attr) 213 214 #define BPCI_CMN_REG_SET(_regv, _attr, _val) \ 215 BHND_PCI_CMN_REG_SET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv), \ 216 BHND_ ## _attr, (_val)) 217 218 #define BPCI_CMN_REG_GET(_regv, _attr) \ 219 BHND_PCI_CMN_REG_GET(BHND_PCI_SOFTC(_sc)->regfmt, (_regv), \ 220 BHND_ ## _attr) 221 222 static int 223 bhnd_pci_hostb_attach(device_t dev) 224 { 225 struct bhnd_pcihb_softc *sc; 226 int error; 227 228 sc = device_get_softc(dev); 229 sc->dev = dev; 230 sc->quirks = bhnd_device_quirks(dev, bhnd_pci_devs, 231 sizeof(bhnd_pci_devs[0])); 232 233 /* Find the host PCI bridge device */ 234 sc->pci_dev = bhnd_find_bridge_root(dev, devclass_find("pci")); 235 if (sc->pci_dev == NULL) { 236 device_printf(dev, "parent pci bridge device not found\n"); 237 return (ENXIO); 238 } 239 240 /* Common setup */ 241 if ((error = bhnd_pci_generic_attach(dev))) 242 return (error); 243 244 /* Apply early single-shot work-arounds */ 245 if ((error = bhnd_pci_wars_early_once(sc))) 246 goto failed; 247 248 /* Apply attach/resume work-arounds */ 249 if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_ATTACH))) 250 goto failed; 251 252 return (0); 253 254 failed: 255 bhnd_pci_generic_detach(dev); 256 return (error); 257 } 258 259 static int 260 bhnd_pci_hostb_detach(device_t dev) 261 { 262 struct bhnd_pcihb_softc *sc; 263 int error; 264 265 sc = device_get_softc(dev); 266 267 /* Apply suspend/detach work-arounds */ 268 if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_DETACH))) 269 return (error); 270 271 return (bhnd_pci_generic_detach(dev)); 272 } 273 274 static int 275 bhnd_pci_hostb_suspend(device_t dev) 276 { 277 struct bhnd_pcihb_softc *sc; 278 int error; 279 280 sc = device_get_softc(dev); 281 282 /* Apply suspend/detach work-arounds */ 283 if ((error = bhnd_pci_wars_hwdown(sc, BHND_PCI_WAR_SUSPEND))) 284 return (error); 285 286 return (bhnd_pci_generic_suspend(dev)); 287 } 288 289 static int 290 bhnd_pci_hostb_resume(device_t dev) 291 { 292 struct bhnd_pcihb_softc *sc; 293 int error; 294 295 sc = device_get_softc(dev); 296 297 if ((error = bhnd_pci_generic_resume(dev))) 298 return (error); 299 300 /* Apply attach/resume work-arounds */ 301 if ((error = bhnd_pci_wars_hwup(sc, BHND_PCI_WAR_RESUME))) { 302 bhnd_pci_generic_detach(dev); 303 return (error); 304 } 305 306 return (0); 307 } 308 309 /** 310 * Apply any hardware work-arounds that must be executed exactly once, early in 311 * the attach process. 312 * 313 * This must be called after core enumeration and discovery of all applicable 314 * quirks, but prior to probe/attach of any cores, parsing of 315 * SPROM, etc. 316 */ 317 static int 318 bhnd_pci_wars_early_once(struct bhnd_pcihb_softc *sc) 319 { 320 int error; 321 322 /* Set PCI latency timer */ 323 if (sc->quirks & BHND_PCI_QUIRK_960NS_LATTIM_OVR) { 324 pci_write_config(sc->pci_dev, PCIR_LATTIMER, 0x20 /* 960ns */, 325 1); 326 } 327 328 /* Determine whether ASPM/CLKREQ should be forced on, or forced off. */ 329 if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 330 struct bhnd_board_info board; 331 bool aspm_en; 332 333 /* Fetch board info */ 334 if ((error = bhnd_read_board_info(sc->dev, &board))) 335 return (error); 336 337 /* Check board flags */ 338 aspm_en = true; 339 if (board.board_flags2 & BHND_BFL2_PCIEWAR_OVR) 340 aspm_en = false; 341 342 /* Early Apple devices did not (but should have) set 343 * BHND_BFL2_PCIEWAR_OVR in SPROM. */ 344 if (sc->quirks & BHND_PCIE_QUIRK_BFL2_PCIEWAR_EN) 345 aspm_en = false; 346 347 sc->aspm_quirk_override.aspm_en = aspm_en; 348 } 349 350 /* Determine correct polarity by observing the attach-time PCIe PHY 351 * link status. This is used later to reset/force the SerDes 352 * polarity */ 353 if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) { 354 uint32_t st; 355 bool inv; 356 357 st = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_PLP_STATUSREG); 358 inv = ((st & BHND_PCIE_PLP_POLARITY_INV) != 0); 359 sc->sdr9_quirk_polarity.inv = inv; 360 } 361 362 /* Override maximum read request size */ 363 if (bhnd_get_class(sc->dev) == BHND_DEVCLASS_PCIE) { 364 int msize; 365 366 msize = 128; /* compatible with all PCIe-G1 core revisions */ 367 if (sc->quirks & BHND_PCIE_QUIRK_DEFAULT_MRRS_512) 368 msize = 512; 369 370 if (pci_set_max_read_req(sc->pci_dev, msize) == 0) 371 panic("set mrrs on non-PCIe device"); 372 } 373 374 return (0); 375 } 376 377 /** 378 * Apply any hardware workarounds that are required upon attach or resume 379 * of the bridge device. 380 */ 381 static int 382 bhnd_pci_wars_hwup(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state) 383 { 384 /* Note that the order here matters; these work-arounds 385 * should not be re-ordered without careful review of their 386 * interdependencies */ 387 388 /* Enable PCI prefetch/burst/readmulti flags */ 389 if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST || 390 sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI) 391 { 392 uint32_t sbp2; 393 sbp2 = BHND_PCI_READ_4(sc, BHND_PCI_SBTOPCI2); 394 395 if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_PREF_BURST) 396 sbp2 |= (BHND_PCI_SBTOPCI_PREF|BHND_PCI_SBTOPCI_BURST); 397 398 if (sc->quirks & BHND_PCI_QUIRK_SBTOPCI2_READMULTI) 399 sbp2 |= BHND_PCI_SBTOPCI_RC_READMULTI; 400 401 BHND_PCI_WRITE_4(sc, BHND_PCI_SBTOPCI2, sbp2); 402 } 403 404 /* Disable PCI CLKRUN# */ 405 if (sc->quirks & BHND_PCI_QUIRK_CLKRUN_DSBL) { 406 uint32_t ctl; 407 408 ctl = BHND_PCI_READ_4(sc, BHND_PCI_CLKRUN_CTL); 409 ctl |= BHND_PCI_CLKRUN_DSBL; 410 BHND_PCI_WRITE_4(sc, BHND_PCI_CLKRUN_CTL, ctl); 411 } 412 413 /* Enable TLP unmatched address handling work-around */ 414 if (sc->quirks & BHND_PCIE_QUIRK_UR_STATUS_FIX) { 415 uint32_t wrs; 416 wrs = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG); 417 wrs |= BHND_PCIE_TLP_WORKAROUND_URBIT; 418 BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_TLP_WORKAROUNDSREG, wrs); 419 } 420 421 /* Adjust SerDes CDR tuning to ensure that CDR is stable before sending 422 * data during L0s to L0 exit transitions. */ 423 if (sc->quirks & BHND_PCIE_QUIRK_SDR9_L0s_HANG) { 424 uint16_t sdv; 425 426 /* Set RX track/acquire timers to 2.064us/40.96us */ 427 sdv = BPCI_REG_SET(0, PCIE_SDR9_RX_TIMER1_LKTRK, (2064/16)); 428 sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_TIMER1_LKACQ, 429 (40960/1024)); 430 BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 431 BHND_PCIE_SDR9_RX_TIMER1, sdv); 432 433 /* Apply CDR frequency workaround */ 434 sdv = BHND_PCIE_SDR9_RX_CDR_FREQ_OVR_EN; 435 sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDR_FREQ_OVR, 0x0); 436 BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 437 BHND_PCIE_SDR9_RX_CDR, sdv); 438 439 /* Apply CDR BW tunings */ 440 sdv = 0; 441 sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGTRK, 0x2); 442 sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_INTGACQ, 0x4); 443 sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPTRK, 0x6); 444 sdv = BPCI_REG_SET(sdv, PCIE_SDR9_RX_CDRBW_PROPACQ, 0x6); 445 BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 446 BHND_PCIE_SDR9_RX_CDRBW, sdv); 447 } 448 449 /* Force correct SerDes polarity */ 450 if (sc->quirks & BHND_PCIE_QUIRK_SDR9_POLARITY) { 451 uint16_t rxctl; 452 453 rxctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_TXRX, 454 BHND_PCIE_SDR9_RX_CTRL); 455 456 rxctl |= BHND_PCIE_SDR9_RX_CTRL_FORCE; 457 if (sc->sdr9_quirk_polarity.inv) 458 rxctl |= BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV; 459 else 460 rxctl &= ~BHND_PCIE_SDR9_RX_CTRL_POLARITY_INV; 461 462 BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_TXRX, 463 BHND_PCIE_SDR9_RX_CTRL, rxctl); 464 } 465 466 /* Disable startup retry on PLL frequency detection failure */ 467 if (sc->quirks & BHND_PCIE_QUIRK_SDR9_NO_FREQRETRY) { 468 uint16_t pctl; 469 470 pctl = BHND_PCI_MDIO_READ(sc, BHND_PCIE_PHY_SDR9_PLL, 471 BHND_PCIE_SDR9_PLL_CTRL); 472 473 pctl &= ~BHND_PCIE_SDR9_PLL_CTRL_FREQDET_EN; 474 BHND_PCI_MDIO_WRITE(sc, BHND_PCIE_PHY_SDR9_PLL, 475 BHND_PCIE_SDR9_PLL_CTRL, pctl); 476 } 477 478 /* Explicitly enable PCI-PM */ 479 if (sc->quirks & BHND_PCIE_QUIRK_PCIPM_REQEN) { 480 uint32_t lcreg; 481 lcreg = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_LCREG); 482 lcreg |= BHND_PCIE_DLLP_LCREG_PCIPM_EN; 483 BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_LCREG, lcreg); 484 } 485 486 /* Adjust L1 timer to fix slow L1->L0 transitions */ 487 if (sc->quirks & BHND_PCIE_QUIRK_L1_IDLE_THRESH) { 488 uint32_t pmt; 489 pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 490 pmt = BPCI_REG_SET(pmt, PCIE_L1THRESHOLDTIME, 491 BHND_PCIE_L1THRESHOLD_WARVAL); 492 BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 493 } 494 495 /* Extend L1 timer for better performance. 496 * TODO: We could enable/disable this on demand for better power 497 * savings if we tie this to HT clock request handling */ 498 if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) { 499 uint32_t pmt; 500 pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 501 pmt |= BHND_PCIE_ASPMTIMER_EXTEND; 502 BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 503 } 504 505 /* Override ASPM/ECPM settings in SPROM shadow and PCIER_LINK_CTL */ 506 if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 507 bus_size_t reg; 508 uint16_t cfg; 509 510 /* Set ASPM L1/L0s flags in SPROM shadow */ 511 reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_ASPM_OFFSET; 512 cfg = BHND_PCI_READ_2(sc, reg); 513 514 if (sc->aspm_quirk_override.aspm_en) 515 cfg |= BHND_PCIE_SRSH_ASPM_ENB; 516 else 517 cfg &= ~BHND_PCIE_SRSH_ASPM_ENB; 518 519 BHND_PCI_WRITE_2(sc, reg, cfg); 520 521 522 /* Set ASPM/ECPM (CLKREQ) flags in PCIe link control register */ 523 cfg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2); 524 525 if (sc->aspm_quirk_override.aspm_en) 526 cfg |= PCIEM_LINK_CTL_ASPMC; 527 else 528 cfg &= ~PCIEM_LINK_CTL_ASPMC; 529 530 cfg &= ~PCIEM_LINK_CTL_ECPM; /* CLKREQ# */ 531 532 pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, cfg, 2); 533 534 /* Set CLKREQ (ECPM) flags in SPROM shadow */ 535 reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_CLKREQ_OFFSET_R5; 536 cfg = BHND_PCI_READ_2(sc, reg); 537 538 if (sc->aspm_quirk_override.aspm_en) 539 cfg |= BHND_PCIE_SRSH_CLKREQ_ENB; 540 else 541 cfg &= ~BHND_PCIE_SRSH_CLKREQ_ENB; 542 543 BHND_PCI_WRITE_2(sc, reg, cfg); 544 } 545 546 /* Enable L23READY_EXIT_NOPRST if not already set in SPROM. */ 547 if (sc->quirks & BHND_PCIE_QUIRK_SPROM_L23_PCI_RESET) { 548 bus_size_t reg; 549 uint16_t cfg; 550 551 /* Fetch the misc cfg flags from SPROM */ 552 reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_PCIE_MISC_CONFIG; 553 cfg = BHND_PCI_READ_2(sc, reg); 554 555 /* Write EXIT_NOPRST flag if not already set in SPROM */ 556 if (!(cfg & BHND_PCIE_SRSH_L23READY_EXIT_NOPRST)) { 557 cfg |= BHND_PCIE_SRSH_L23READY_EXIT_NOPRST; 558 BHND_PCI_WRITE_2(sc, reg, cfg); 559 } 560 } 561 562 /* Disable SerDes PLL down */ 563 if (sc->quirks & BHND_PCIE_QUIRK_SERDES_NOPLLDOWN) { 564 device_t bhnd, chipc; 565 bus_size_t reg; 566 567 bhnd = device_get_parent(sc->dev); 568 chipc = bhnd_bus_find_child(bhnd, BHND_DEVCLASS_CC, 0); 569 KASSERT(chipc != NULL, ("missing chipcommon device")); 570 571 /* Write SerDes PLL disable flag to the ChipCommon core */ 572 BHND_CHIPC_WRITE_CHIPCTRL(chipc, CHIPCTRL_4321_PLL_DOWN, 573 CHIPCTRL_4321_PLL_DOWN); 574 575 /* Clear SPROM shadow backdoor register */ 576 reg = BHND_PCIE_SPROM_SHADOW + BHND_PCIE_SRSH_BD_OFFSET; 577 BHND_PCI_WRITE_2(sc, reg, 0); 578 } 579 580 /* Adjust TX drive strength and pre-emphasis coefficient */ 581 if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_ADJUST) { 582 uint16_t txdrv; 583 584 /* Fetch current TX driver parameters */ 585 txdrv = BHND_PCI_MDIO_READ_EXT(sc, BHND_PCIE_PHYADDR_SD, 586 BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER); 587 588 /* Set 700mV drive strength */ 589 if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_700MV) { 590 txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF, 591 BHND_PCIE_APPLE_TX_P2_COEFF_700MV); 592 593 txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER, 594 BHND_PCIE_APPLE_TX_IDRIVER_700MV); 595 } 596 597 /* ... or, set max drive strength */ 598 if (sc->quirks & BHND_PCIE_QUIRK_SERDES_TXDRV_MAX) { 599 txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_P2_COEFF, 600 BHND_PCIE_APPLE_TX_P2_COEFF_MAX); 601 602 txdrv = BPCI_REG_SET(txdrv, PCIE_SD_TX_DRIVER_IDRIVER, 603 BHND_PCIE_APPLE_TX_IDRIVER_MAX); 604 } 605 606 BHND_PCI_MDIO_WRITE_EXT(sc, BHND_PCIE_PHYADDR_SD, 607 BHND_PCIE_SD_REGS_TX0, BHND_PCIE_SD_TX_DRIVER, txdrv); 608 } 609 610 return (0); 611 } 612 613 /** 614 * Apply any hardware workarounds that are required upon detach or suspend 615 * of the bridge device. 616 */ 617 static int 618 bhnd_pci_wars_hwdown(struct bhnd_pcihb_softc *sc, bhnd_pci_war_state state) 619 { 620 /* Reduce L1 timer for better power savings. 621 * TODO: We could enable/disable this on demand for better power 622 * savings if we tie this to HT clock request handling */ 623 if (sc->quirks & BHND_PCIE_QUIRK_L1_TIMER_PERF) { 624 uint32_t pmt; 625 pmt = BHND_PCI_PROTO_READ_4(sc, BHND_PCIE_DLLP_PMTHRESHREG); 626 pmt &= ~BHND_PCIE_ASPMTIMER_EXTEND; 627 BHND_PCI_PROTO_WRITE_4(sc, BHND_PCIE_DLLP_PMTHRESHREG, pmt); 628 } 629 630 /* Enable CLKREQ (ECPM). If suspending, also disable ASPM L1 entry */ 631 if (sc->quirks & BHND_PCIE_QUIRK_ASPM_OVR) { 632 uint16_t lcreg; 633 634 lcreg = pcie_read_config(sc->pci_dev, PCIER_LINK_CTL, 2); 635 636 lcreg |= PCIEM_LINK_CTL_ECPM; /* CLKREQ# */ 637 if (state == BHND_PCI_WAR_SUSPEND) 638 lcreg &= ~PCIEM_LINK_CTL_ASPMC_L1; 639 640 pcie_write_config(sc->pci_dev, PCIER_LINK_CTL, lcreg, 2); 641 } 642 643 return (0); 644 } 645 646 static device_method_t bhnd_pci_hostb_methods[] = { 647 /* Device interface */ 648 DEVMETHOD(device_attach, bhnd_pci_hostb_attach), 649 DEVMETHOD(device_detach, bhnd_pci_hostb_detach), 650 DEVMETHOD(device_suspend, bhnd_pci_hostb_suspend), 651 DEVMETHOD(device_resume, bhnd_pci_hostb_resume), 652 653 DEVMETHOD_END 654 }; 655 656 DEFINE_CLASS_1(bhnd_hostb, bhnd_pci_hostb_driver, bhnd_pci_hostb_methods, 657 sizeof(struct bhnd_pcihb_softc), bhnd_pci_driver); 658 DRIVER_MODULE(bhnd_pci_hostb, bhnd, bhnd_pci_hostb_driver, bhnd_hostb_devclass, 0, 0); 659 660 MODULE_VERSION(bhnd_pci_hostb, 1); 661 MODULE_DEPEND(bhnd_pci_hostb, bhnd, 1, 1, 1); 662 MODULE_DEPEND(bhnd_pci_hostb, bhnd_pci, 1, 1, 1); 663