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