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