TbtSmm.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764
  1. /** @file
  2. Thunderbolt initialization in SMM.
  3. Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. //
  7. // Module specific Includes
  8. //
  9. #include <Library/BaseMemoryLib.h>
  10. #include <Library/BaseLib.h>
  11. #include <Library/GpioLib.h>
  12. #include <TbtBoardInfo.h>
  13. #include <Protocol/TbtNvsArea.h>
  14. #include <PchAccess.h>
  15. #include <Library/BaseLib.h>
  16. #include <Library/PciSegmentLib.h>
  17. #include <Library/PchInfoLib.h>
  18. #include <Library/IoLib.h>
  19. #include <Library/SmmServicesTableLib.h>
  20. #include <Protocol/SmmSxDispatch2.h>
  21. #include <Protocol/SmmSwDispatch2.h>
  22. #include <Uefi/UefiSpec.h>
  23. #include <Library/UefiLib.h>
  24. #include <Library/UefiRuntimeServicesTableLib.h>
  25. #include <Library/UefiBootServicesTableLib.h>
  26. #include <Library/DebugLib.h>
  27. #include <Library/HobLib.h>
  28. #include <Guid/HobList.h>
  29. #include "TbtSmiHandler.h"
  30. #include <PcieRegs.h>
  31. #include <Protocol/SaPolicy.h>
  32. #include <Protocol/DxeTbtPolicy.h>
  33. #include <Library/PchPmcLib.h>
  34. #define P2P_BRIDGE (((PCI_CLASS_BRIDGE) << 8) | (PCI_CLASS_BRIDGE_P2P))
  35. #define CMD_BM_MEM_IO (CMD_BUS_MASTER | BIT1 | BIT0)
  36. #define DISBL_IO_REG1C 0x01F1
  37. #define DISBL_MEM32_REG20 0x0000FFF0
  38. #define DISBL_PMEM_REG24 0x0001FFF1
  39. #define DOCK_BUSSES 8
  40. #define PCI_CAPABILITY_ID_PCIEXP 0x10
  41. #define PCI_CAPBILITY_POINTER_OFFSET 0x34
  42. #define LTR_MAX_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Snoop Latency can we put like this ?
  43. #define LTR_MAX_NON_SNOOP_LATENCY_VALUE 0x0846 ///< Intel recommended maximum value for Non-Snoop Latency can we put like this ?
  44. GLOBAL_REMOVE_IF_UNREFERENCED TBT_NVS_AREA *mTbtNvsAreaPtr;
  45. GLOBAL_REMOVE_IF_UNREFERENCED UINT8 gCurrentDiscreteTbtRootPort;
  46. GLOBAL_REMOVE_IF_UNREFERENCED UINT8 gCurrentDiscreteTbtRootPortType;
  47. GLOBAL_REMOVE_IF_UNREFERENCED UINT16 TbtLtrMaxSnoopLatency;
  48. GLOBAL_REMOVE_IF_UNREFERENCED UINT16 TbtLtrMaxNoSnoopLatency;
  49. GLOBAL_REMOVE_IF_UNREFERENCED UINT8 gDTbtPcieRstSupport;
  50. GLOBAL_REMOVE_IF_UNREFERENCED TBT_INFO_HOB *gTbtInfoHob = NULL;
  51. STATIC UINTN mPciExpressBaseAddress;
  52. STATIC UINT8 TbtSegment = 0;
  53. VOID
  54. GpioWrite (
  55. IN UINT32 GpioNumber,
  56. IN BOOLEAN Value
  57. )
  58. {
  59. GpioSetOutputValue (GpioNumber, (UINT32)Value);
  60. }
  61. /**
  62. Search and return the offset of desired Pci Express Capability ID
  63. CAPID list:
  64. 0x0001 = Advanced Error Reporting Capability
  65. 0x0002 = Virtual Channel Capability
  66. 0x0003 = Device Serial Number Capability
  67. 0x0004 = Power Budgeting Capability
  68. @param[in] Bus Pci Bus Number
  69. @param[in] Device Pci Device Number
  70. @param[in] Function Pci Function Number
  71. @param[in] CapId Extended CAPID to search for
  72. @retval 0 CAPID not found
  73. @retval Other CAPID found, Offset of desired CAPID
  74. **/
  75. UINT16
  76. PcieFindExtendedCapId (
  77. IN UINT8 Bus,
  78. IN UINT8 Device,
  79. IN UINT8 Function,
  80. IN UINT16 CapId
  81. )
  82. {
  83. UINT16 CapHeaderOffset;
  84. UINT16 CapHeaderId;
  85. UINT64 DeviceBase;
  86. DeviceBase = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, Function, 0);
  87. ///
  88. /// Start to search at Offset 0x100
  89. /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
  90. ///
  91. CapHeaderId = 0;
  92. CapHeaderOffset = 0x100;
  93. while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {
  94. CapHeaderId = PciSegmentRead16 (DeviceBase + CapHeaderOffset);
  95. if (CapHeaderId == CapId) {
  96. return CapHeaderOffset;
  97. }
  98. ///
  99. /// Each capability must be DWORD aligned.
  100. /// The bottom two bits of all pointers are reserved and must be implemented as 00b
  101. /// although software must mask them to allow for future uses of these bits.
  102. ///
  103. CapHeaderOffset = (PciSegmentRead16 (DeviceBase + CapHeaderOffset + 2) >> 4) & ((UINT16) ~(BIT0 | BIT1));
  104. }
  105. return 0;
  106. }
  107. /**
  108. Find the Offset to a given Capabilities ID
  109. CAPID list:
  110. 0x01 = PCI Power Management Interface
  111. 0x04 = Slot Identification
  112. 0x05 = MSI Capability
  113. 0x10 = PCI Express Capability
  114. @param[in] Bus Pci Bus Number
  115. @param[in] Device Pci Device Number
  116. @param[in] Function Pci Function Number
  117. @param[in] CapId CAPID to search for
  118. @retval 0 CAPID not found
  119. @retval Other CAPID found, Offset of desired CAPID
  120. **/
  121. UINT8
  122. PcieFindCapId (
  123. IN UINT8 Segment,
  124. IN UINT8 Bus,
  125. IN UINT8 Device,
  126. IN UINT8 Function,
  127. IN UINT8 CapId
  128. )
  129. {
  130. UINT8 CapHeaderOffset;
  131. UINT8 CapHeaderId;
  132. UINT64 DeviceBase;
  133. DeviceBase = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0);
  134. if ((PciSegmentRead8 (DeviceBase + PCI_PRIMARY_STATUS_OFFSET) & EFI_PCI_STATUS_CAPABILITY) == 0x00) {
  135. ///
  136. /// Function has no capability pointer
  137. ///
  138. return 0;
  139. }
  140. ///
  141. /// Check the header layout to determine the Offset of Capabilities Pointer Register
  142. ///
  143. if ((PciSegmentRead8 (DeviceBase + PCI_HEADER_TYPE_OFFSET) & HEADER_LAYOUT_CODE) == (HEADER_TYPE_CARDBUS_BRIDGE)) {
  144. ///
  145. /// If CardBus bridge, start at Offset 0x14
  146. ///
  147. CapHeaderOffset = 0x14;
  148. } else {
  149. ///
  150. /// Otherwise, start at Offset 0x34
  151. ///
  152. CapHeaderOffset = 0x34;
  153. }
  154. ///
  155. /// Get Capability Header, A pointer value of 00h is used to indicate the last capability in the list.
  156. ///
  157. CapHeaderId = 0;
  158. CapHeaderOffset = PciSegmentRead8 (DeviceBase + CapHeaderOffset) & ((UINT8) ~(BIT0 | BIT1));
  159. while (CapHeaderOffset != 0 && CapHeaderId != 0xFF) {
  160. CapHeaderId = PciSegmentRead8 (DeviceBase + CapHeaderOffset);
  161. if (CapHeaderId == CapId) {
  162. return CapHeaderOffset;
  163. }
  164. ///
  165. /// Each capability must be DWORD aligned.
  166. /// The bottom two bits of all pointers (including the initial pointer at 34h) are reserved
  167. /// and must be implemented as 00b although software must mask them to allow for future uses of these bits.
  168. ///
  169. CapHeaderOffset = PciSegmentRead8 (DeviceBase + CapHeaderOffset + 1) & ((UINT8) ~(BIT0 | BIT1));
  170. }
  171. return 0;
  172. }
  173. /**
  174. This function configures the L1 Substates.
  175. It can be used for Rootport and endpoint devices.
  176. @param[in] DownstreamPort Indicates if the device about to be programmed is a downstream port
  177. @param[in] DeviceBase Device PCI configuration base address
  178. @param[in] L1SubstateExtCapOffset Pointer to L1 Substate Capability Structure
  179. @param[in] PortL1SubstateCapSupport L1 Substate capability setting
  180. @param[in] PortCommonModeRestoreTime Common Mode Restore Time
  181. @param[in] PortTpowerOnValue Tpower_on Power On Wait Time
  182. @param[in] PortTpowerOnScale Tpower-on Scale
  183. @retval none
  184. **/
  185. VOID
  186. ConfigureL1s (
  187. IN UINTN DeviceBase,
  188. IN UINT16 L1SubstateExtCapOffset,
  189. IN UINT32 PortL1SubstateCapSupport,
  190. IN UINT32 PortCommonModeRestoreTime,
  191. IN UINT32 PortTpowerOnValue,
  192. IN UINT32 PortTpowerOnScale,
  193. IN UINT16 MaxLevel
  194. )
  195. {
  196. PciSegmentAndThenOr32 (
  197. DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  198. (UINT32) ~(0xFF00),
  199. (UINT32) PortCommonModeRestoreTime << 8
  200. );
  201. PciSegmentAnd32(DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET, 0xFFFFFF04);
  202. PciSegmentOr32(DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL2_OFFSET,(UINT32) ((PortTpowerOnValue << N_PCIE_EX_L1SCTL2_POWT) | PortTpowerOnScale));
  203. PciSegmentAndThenOr32 (
  204. DeviceBase + L1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  205. (UINT32) ~(0xE3FF0000),
  206. (UINT32) (BIT30 | BIT23 | BIT21)
  207. );
  208. }
  209. VOID
  210. RootportL1sSupport (
  211. IN UINT8 Bus,
  212. IN UINT8 Dev,
  213. IN UINT8 Fun,
  214. IN UINT16 RootL1SubstateExtCapOffset,
  215. IN UINT16 MaxL1Level
  216. )
  217. {
  218. UINTN ComponentABaseAddress;
  219. UINTN ComponentBBaseAddress;
  220. UINT8 SecBus;
  221. UINT32 PortL1SubstateCapSupport;
  222. UINT32 PortCommonModeRestoreTime;
  223. UINT32 PortTpowerOnValue;
  224. UINT32 PortTpowerOnScale;
  225. UINT16 ComponentBL1SubstateExtCapOffset;
  226. UINT32 ComponentBL1Substates;
  227. UINT32 ComponentBCommonModeRestoreTime;
  228. UINT32 ComponentBTpowerOnValue;
  229. UINT32 ComponentBTpowerOnScale;
  230. UINT32 Data32;
  231. PortL1SubstateCapSupport = 0;
  232. PortCommonModeRestoreTime = 0;
  233. PortTpowerOnValue = 0;
  234. PortTpowerOnScale = 0;
  235. Data32 = 0;
  236. ComponentABaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  237. if (RootL1SubstateExtCapOffset != 0) {
  238. Data32 = PciSegmentRead32 (ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
  239. PortL1SubstateCapSupport = (Data32) & 0x0F;
  240. PortCommonModeRestoreTime = (Data32 >> 8) & 0xFF;
  241. PortTpowerOnScale = (Data32 >> 16) & 0x3;
  242. PortTpowerOnValue = (Data32 >> 19) & 0x1F;
  243. } else {
  244. MaxL1Level = 0; // If L1 Substates from Root Port side is disable, then Disable from Device side also.
  245. }
  246. SecBus = PciSegmentRead8 (ComponentABaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  247. ComponentBBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, SecBus, 0, 0, 0);
  248. if (PciSegmentRead16 (ComponentBBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  249. ComponentBL1SubstateExtCapOffset = PcieFindExtendedCapId (
  250. SecBus,
  251. 0,
  252. 0,
  253. V_PCIE_EX_L1S_CID
  254. );
  255. if (ComponentBL1SubstateExtCapOffset != 0) {
  256. ComponentBL1Substates = PciSegmentRead32 (ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCAP_OFFSET);
  257. ComponentBCommonModeRestoreTime = (ComponentBL1Substates >> 8) & 0xFF;
  258. ComponentBTpowerOnScale = (ComponentBL1Substates >> 16) & 0x3;
  259. ComponentBTpowerOnValue = (ComponentBL1Substates >> 19) & 0x1F;
  260. if (MaxL1Level == 3) {
  261. if (Data32 >= ComponentBL1Substates) {
  262. if (~(Data32 | BIT2)) {
  263. MaxL1Level = 1;
  264. }
  265. }
  266. else {
  267. if (~(ComponentBL1Substates | BIT2)) {
  268. MaxL1Level = 1;
  269. }
  270. }
  271. }
  272. if (MaxL1Level == 3) {
  273. ConfigureL1s (
  274. ComponentABaseAddress,
  275. RootL1SubstateExtCapOffset,
  276. PortL1SubstateCapSupport,
  277. ComponentBCommonModeRestoreTime,
  278. ComponentBTpowerOnValue,
  279. ComponentBTpowerOnScale,
  280. MaxL1Level
  281. );
  282. ConfigureL1s (
  283. ComponentBBaseAddress,
  284. ComponentBL1SubstateExtCapOffset,
  285. ComponentBL1Substates,
  286. PortCommonModeRestoreTime,
  287. PortTpowerOnValue,
  288. PortTpowerOnScale,
  289. MaxL1Level
  290. );
  291. }
  292. if (MaxL1Level == 1) {
  293. PciSegmentOr32 (
  294. ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  295. (UINT32) (BIT3 | BIT1)
  296. );
  297. PciSegmentOr32 (
  298. ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  299. (UINT32) (BIT3 | BIT1)
  300. );
  301. }
  302. else {
  303. if (RootL1SubstateExtCapOffset != 0) {
  304. PciSegmentOr32 (
  305. ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  306. (UINT32) (BIT3 | BIT1)
  307. );
  308. PciSegmentOr32 (
  309. ComponentABaseAddress + RootL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  310. (UINT32) (BIT2 | BIT0)
  311. );
  312. }
  313. if (ComponentBL1SubstateExtCapOffset != 0) {
  314. PciSegmentOr32 (
  315. ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  316. (UINT32) (BIT3 | BIT1)
  317. );
  318. PciSegmentOr32 (
  319. ComponentBBaseAddress + ComponentBL1SubstateExtCapOffset + R_PCIE_EX_L1SCTL1_OFFSET,
  320. (UINT32) (BIT2 | BIT0)
  321. );
  322. }
  323. }
  324. }
  325. }
  326. }
  327. VOID
  328. MultiFunctionDeviceAspm (
  329. IN UINT8 Bus,
  330. IN UINT8 Dev
  331. )
  332. {
  333. UINT16 LowerAspm;
  334. UINT16 AspmVal;
  335. UINT8 Fun;
  336. UINT64 DeviceBaseAddress;
  337. UINT8 CapHeaderOffset;
  338. LowerAspm = 3; // L0s and L1 Supported
  339. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  340. //
  341. // Check for Device availability
  342. //
  343. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  344. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  345. // Device not present
  346. continue;
  347. }
  348. CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
  349. AspmVal = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
  350. if (LowerAspm > AspmVal) {
  351. LowerAspm = AspmVal;
  352. }
  353. } //Fun
  354. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  355. //
  356. // Check for Device availability
  357. //
  358. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  359. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  360. //
  361. // Device not present
  362. //
  363. continue;
  364. }
  365. CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
  366. PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, LowerAspm);
  367. } //Fun
  368. }
  369. UINT16
  370. LimitAspmLevel (
  371. IN UINT16 SelectedAspm,
  372. IN UINT16 MaxAspmLevel
  373. )
  374. {
  375. SelectedAspm = SelectedAspm & MaxAspmLevel;
  376. return SelectedAspm;
  377. }
  378. UINT16
  379. FindOptimalAspm (
  380. IN UINT16 ComponentAaspm,
  381. IN UINT16 ComponentBaspm
  382. )
  383. {
  384. UINT16 SelectedAspm;
  385. SelectedAspm = ComponentAaspm & ComponentBaspm;
  386. return SelectedAspm;
  387. }
  388. UINT16
  389. FindComponentBaspm (
  390. IN UINT8 Bus,
  391. IN UINT8 MaxBus
  392. )
  393. {
  394. UINT8 BusNo;
  395. UINT8 DevNo;
  396. UINT8 FunNo;
  397. UINT64 DevBaseAddress;
  398. UINT8 RegVal;
  399. UINT8 SecBusNo;
  400. UINT16 SelectedAspm; // No ASPM Support
  401. UINT8 CapHeaderOffset_B;
  402. BOOLEAN AspmFound;
  403. SelectedAspm = 0;
  404. AspmFound = FALSE;
  405. for (BusNo = MaxBus; (BusNo != 0xFF) && (!AspmFound); --BusNo) {
  406. for (DevNo = 0; (DevNo <= PCI_MAX_DEVICE) && (!AspmFound); ++DevNo) {
  407. for (FunNo = 0; (FunNo <= PCI_MAX_FUNC) && (!AspmFound); ++FunNo) {
  408. //
  409. // Check for Device availability
  410. //
  411. DevBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, BusNo, DevNo, FunNo, 0);
  412. if (PciSegmentRead16 (DevBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  413. //
  414. // Device not present
  415. //
  416. continue;
  417. }
  418. RegVal = PciSegmentRead8 (DevBaseAddress + PCI_HEADER_TYPE_OFFSET);
  419. if ((RegVal & (BIT0 + BIT1 + BIT2 + BIT3 + BIT4 + BIT5 + BIT6)) != 0x01) {
  420. //
  421. // Not a PCI-to-PCI bridges device
  422. //
  423. continue;
  424. }
  425. SecBusNo = PciSegmentRead8 (DevBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  426. if (SecBusNo == Bus) {
  427. //
  428. // This is the Rootbridge for the given 'Bus' device
  429. //
  430. CapHeaderOffset_B = PcieFindCapId (TbtSegment, BusNo, DevNo, FunNo, 0x10);
  431. SelectedAspm = (PciSegmentRead16 (DevBaseAddress + CapHeaderOffset_B + 0x00C) >> 10) & 3;
  432. AspmFound = TRUE;
  433. }
  434. } //FunNo
  435. } //DevNo
  436. } //BusNo
  437. return (SelectedAspm);
  438. }
  439. VOID
  440. NoAspmSupport (
  441. IN UINT8 Bus,
  442. IN UINT8 Dev,
  443. IN UINT8 Fun,
  444. IN UINT8 CapHeaderOffset
  445. )
  446. {
  447. UINT64 DeviceBaseAddress;
  448. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  449. PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, 0x00);
  450. }
  451. VOID
  452. EndpointAspmSupport (
  453. IN UINT8 Bus,
  454. IN UINT8 Dev,
  455. IN UINT8 Fun,
  456. IN UINT8 CapHeaderOffset,
  457. IN UINT8 MaxBus,
  458. IN UINT16 MaxAspmLevel
  459. )
  460. {
  461. UINT64 DeviceBaseAddress;
  462. UINT16 ComponentAaspm;
  463. UINT16 ComponentBaspm;
  464. UINT16 SelectedAspm;
  465. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  466. ComponentAaspm = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
  467. ComponentBaspm = FindComponentBaspm (Bus, MaxBus);
  468. SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
  469. SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
  470. PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
  471. }
  472. VOID
  473. UpstreamAspmSupport (
  474. IN UINT8 Bus,
  475. IN UINT8 Dev,
  476. IN UINT8 Fun,
  477. IN UINT8 CapHeaderOffset,
  478. IN UINT8 MaxBus,
  479. IN UINT16 MaxAspmLevel
  480. )
  481. {
  482. UINT64 DeviceBaseAddress;
  483. UINT16 ComponentAaspm;
  484. UINT16 ComponentBaspm;
  485. UINT16 SelectedAspm;
  486. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  487. ComponentAaspm = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
  488. ComponentBaspm = FindComponentBaspm (Bus, MaxBus);
  489. SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
  490. SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
  491. PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
  492. }
  493. VOID
  494. DownstreamAspmSupport (
  495. IN UINT8 Bus,
  496. IN UINT8 Dev,
  497. IN UINT8 Fun,
  498. IN UINT8 CapHeaderOffset,
  499. IN UINT16 MaxAspmLevel
  500. )
  501. {
  502. UINT64 ComponentABaseAddress;
  503. UINT64 ComponentBBaseAddress;
  504. UINT16 ComponentAaspm;
  505. UINT16 ComponentBaspm;
  506. UINT16 SelectedAspm;
  507. UINT8 SecBus;
  508. UINT8 CapHeaderOffset_B;
  509. ComponentABaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  510. ComponentAaspm = (PciSegmentRead16 (ComponentABaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
  511. SecBus = PciSegmentRead8 (ComponentABaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  512. ComponentBBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, SecBus, 0, 0, 0);
  513. ComponentBaspm = 0; // No ASPM Support
  514. if (PciSegmentRead16 (ComponentBBaseAddress + PCI_DEVICE_ID_OFFSET) != 0xFFFF) {
  515. CapHeaderOffset_B = PcieFindCapId (TbtSegment, SecBus, 0, 0, 0x10);
  516. ComponentBaspm = (PciSegmentRead16 (ComponentBBaseAddress + CapHeaderOffset_B + 0x00C) >> 10) & 3;
  517. }
  518. SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
  519. SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
  520. PciSegmentAndThenOr16 (ComponentABaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
  521. }
  522. VOID
  523. RootportAspmSupport (
  524. IN UINT8 Bus,
  525. IN UINT8 Dev,
  526. IN UINT8 Fun,
  527. IN UINT8 CapHeaderOffset,
  528. IN UINT16 MaxAspmLevel
  529. )
  530. {
  531. UINT64 ComponentABaseAddress;
  532. UINT64 ComponentBBaseAddress;
  533. UINT16 ComponentAaspm;
  534. UINT16 ComponentBaspm;
  535. UINT16 SelectedAspm;
  536. UINT8 SecBus;
  537. UINT8 CapHeaderOffset_B;
  538. ComponentABaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  539. ComponentAaspm = (PciSegmentRead16 (ComponentABaseAddress + CapHeaderOffset + 0x00C) >> 10) & 3;
  540. SecBus = PciSegmentRead8 (ComponentABaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  541. ComponentBBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, SecBus, 0, 0, 0);
  542. ComponentBaspm = 0; // No ASPM Support
  543. if (PciSegmentRead16 (ComponentBBaseAddress + PCI_DEVICE_ID_OFFSET) != 0xFFFF) {
  544. CapHeaderOffset_B = PcieFindCapId (TbtSegment, SecBus, 0, 0, 0x10);
  545. ComponentBaspm = (PciSegmentRead16 (ComponentBBaseAddress + CapHeaderOffset_B + 0x00C) >> 10) & 3;
  546. }
  547. SelectedAspm = FindOptimalAspm (ComponentAaspm, ComponentBaspm);
  548. SelectedAspm = LimitAspmLevel (SelectedAspm, MaxAspmLevel);
  549. PciSegmentAndThenOr16 (ComponentABaseAddress + CapHeaderOffset + 0x10, 0xFFFC, SelectedAspm);
  550. }
  551. VOID
  552. ThunderboltEnableAspmWithoutLtr (
  553. IN UINT16 MaxAspmLevel,
  554. IN UINTN RpSegment,
  555. IN UINTN RpBus,
  556. IN UINTN RpDevice,
  557. IN UINTN RpFunction
  558. )
  559. {
  560. UINT8 Bus;
  561. UINT8 Dev;
  562. UINT8 Fun;
  563. UINT8 RootBus;
  564. UINT8 RootDev;
  565. UINT8 RootFun;
  566. UINT8 MinBus;
  567. UINT8 MaxBus;
  568. UINT16 DeviceId;
  569. UINT64 DeviceBaseAddress;
  570. UINT8 RegVal;
  571. UINT8 CapHeaderOffset;
  572. UINT16 DevicePortType;
  573. MinBus = 0;
  574. MaxBus = 0;
  575. MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
  576. MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
  577. DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
  578. if (!(IsTbtHostRouter (DeviceId))) {
  579. return;
  580. }
  581. TbtSegment = (UINT8)RpSegment;
  582. RootBus = (UINT8)RpBus;
  583. RootDev = (UINT8)RpDevice;
  584. RootFun = (UINT8)RpFunction;
  585. //
  586. // Enumerate all the bridges and devices which are available on TBT host controller
  587. //
  588. for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
  589. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  590. //
  591. // Check for Device availability
  592. //
  593. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, 0, 0);
  594. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  595. //
  596. // Device not present
  597. //
  598. continue;
  599. }
  600. RegVal = PciSegmentRead8 (DeviceBaseAddress + PCI_HEADER_TYPE_OFFSET);
  601. if ((RegVal & BIT7) == 0) {
  602. //
  603. // Not a multi-function device
  604. //
  605. continue;
  606. }
  607. MultiFunctionDeviceAspm(Bus, Dev);
  608. } //Dev
  609. } //Bus
  610. for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
  611. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  612. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  613. //
  614. // Check for Device availability
  615. //
  616. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  617. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  618. //
  619. // Device not present
  620. //
  621. continue;
  622. }
  623. CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
  624. DevicePortType = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x002) >> 4) & 0xF;
  625. if(PciSegmentRead8 (DeviceBaseAddress + PCI_CLASSCODE_OFFSET) == PCI_CLASS_SERIAL) {
  626. MaxAspmLevel = (UINT16) 0x1;
  627. }
  628. switch (DevicePortType) {
  629. case 0:
  630. //
  631. // PCI Express Endpoint
  632. //
  633. EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
  634. break;
  635. case 1:
  636. //
  637. // Legacy PCI Express Endpoint
  638. //
  639. EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
  640. break;
  641. case 4:
  642. //
  643. // Root Port of PCI Express Root Complex
  644. //
  645. RootportAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxAspmLevel);
  646. break;
  647. case 5:
  648. //
  649. // Upstream Port of PCI Express Switch
  650. //
  651. UpstreamAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
  652. break;
  653. case 6:
  654. //
  655. // Downstream Port of PCI Express Switch
  656. //
  657. DownstreamAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxAspmLevel);
  658. break;
  659. case 7:
  660. //
  661. // PCI Express to PCI/PCI-X Bridge
  662. //
  663. NoAspmSupport (Bus, Dev, Fun, CapHeaderOffset);
  664. break;
  665. case 8:
  666. //
  667. // PCI/PCI-X to PCI Express Bridge
  668. //
  669. NoAspmSupport (Bus, Dev, Fun, CapHeaderOffset);
  670. break;
  671. case 9:
  672. //
  673. // Root Complex Integrated Endpoint
  674. //
  675. EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
  676. break;
  677. case 10:
  678. //
  679. // Root Complex Event Collector
  680. //
  681. EndpointAspmSupport (Bus, Dev, Fun, CapHeaderOffset, MaxBus, MaxAspmLevel);
  682. break;
  683. default:
  684. break;
  685. }
  686. //
  687. // switch(DevicePortType)
  688. //
  689. }
  690. //
  691. // Fun
  692. //
  693. }
  694. //
  695. // Dev
  696. //
  697. }
  698. //
  699. // Bus
  700. //
  701. CapHeaderOffset = PcieFindCapId (TbtSegment, RootBus, RootDev, RootFun, 0x10);
  702. RootportAspmSupport (RootBus, RootDev, RootFun, CapHeaderOffset, MaxAspmLevel);
  703. }
  704. VOID
  705. ThunderboltEnableL1Sub (
  706. IN UINT16 MaxL1Level,
  707. IN UINTN RpSegment,
  708. IN UINTN RpBus,
  709. IN UINTN RpDevice,
  710. IN UINTN RpFunction
  711. )
  712. {
  713. UINT16 CapHeaderOffsetExtd;
  714. RpBus = 0;
  715. CapHeaderOffsetExtd = PcieFindExtendedCapId ((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, V_PCIE_EX_L1S_CID);
  716. RootportL1sSupport ((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, CapHeaderOffsetExtd, MaxL1Level);
  717. }
  718. VOID
  719. ThunderboltDisableAspmWithoutLtr (
  720. IN UINTN RpSegment,
  721. IN UINTN RpBus,
  722. IN UINTN RpDevice,
  723. IN UINTN RpFunction
  724. )
  725. {
  726. UINT8 Bus;
  727. UINT8 Dev;
  728. UINT8 Fun;
  729. UINT8 RootBus;
  730. UINT8 RootDev;
  731. UINT8 RootFun;
  732. UINT8 MinBus;
  733. UINT8 MaxBus;
  734. UINT16 DeviceId;
  735. UINT64 DeviceBaseAddress;
  736. UINT8 CapHeaderOffset;
  737. MinBus = 0;
  738. MaxBus = 0;
  739. MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
  740. MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
  741. DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
  742. if (!(IsTbtHostRouter (DeviceId))) {
  743. return;
  744. }
  745. TbtSegment = (UINT8)RpSegment;
  746. RootBus = (UINT8)RpBus;
  747. RootDev = (UINT8)RpDevice;
  748. RootFun = (UINT8)RpFunction;
  749. //
  750. // Enumerate all the bridges and devices which are available on TBT host controller
  751. //
  752. for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
  753. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  754. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  755. //
  756. // Check for Device availability
  757. //
  758. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  759. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  760. //
  761. // Device not present
  762. //
  763. continue;
  764. }
  765. CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
  766. PciSegmentAndThenOr16 (DeviceBaseAddress + CapHeaderOffset + 0x10, 0xFFFC, 0x00);
  767. } //Fun
  768. } //Dev
  769. } //Bus
  770. CapHeaderOffset = PcieFindCapId (TbtSegment, RootBus, RootDev, RootFun, 0x10);
  771. NoAspmSupport(RootBus, RootDev, RootFun, CapHeaderOffset);
  772. }
  773. VOID
  774. TbtProgramClkReq (
  775. IN UINT8 Bus,
  776. IN UINT8 Device,
  777. IN UINT8 Function,
  778. IN UINT8 ClkReqSetup
  779. )
  780. {
  781. UINT64 DeviceBaseAddress;
  782. UINT8 CapHeaderOffset;
  783. UINT16 Data16;
  784. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, Function, 0);
  785. CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Device, Function, 0x10);
  786. //
  787. // Check if CLKREQ# is supported
  788. //
  789. if ((PciSegmentRead32 (DeviceBaseAddress + CapHeaderOffset + 0x0C) & BIT18) != 0) {
  790. Data16 = PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x010);
  791. if (ClkReqSetup) {
  792. Data16 = Data16 | BIT8; // Enable Clock Power Management
  793. } else {
  794. Data16 = Data16 & (UINT16)(~BIT8); // Disable Clock Power Management
  795. }
  796. PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffset + 0x010, Data16);
  797. }
  798. }
  799. VOID
  800. TbtProgramPtm(
  801. IN UINT8 Bus,
  802. IN UINT8 Device,
  803. IN UINT8 Function,
  804. IN UINT8 PtmSetup,
  805. IN BOOLEAN IsRoot
  806. )
  807. {
  808. UINT64 DeviceBaseAddress;
  809. UINT16 CapHeaderOffset;
  810. UINT16 PtmControlRegister;
  811. UINT16 PtmCapabilityRegister;
  812. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS(TbtSegment, Bus, Device, Function, 0);
  813. CapHeaderOffset = PcieFindExtendedCapId(Bus, Device, Function, 0x001F /*V_PCIE_EX_PTM_CID*/);
  814. if(CapHeaderOffset != 0) {
  815. PtmCapabilityRegister = PciSegmentRead16(DeviceBaseAddress + CapHeaderOffset + 0x04);
  816. //
  817. // Check if PTM Requester/ Responder capability for the EP/Down stream etc
  818. //
  819. if ((PtmCapabilityRegister & (BIT1 | BIT0)) != 0) {
  820. PtmControlRegister = PciSegmentRead16(DeviceBaseAddress + CapHeaderOffset + 0x08);
  821. if (PtmSetup) {
  822. PtmControlRegister = PtmControlRegister | BIT0; // Enable PTM
  823. if(IsRoot) {
  824. PtmControlRegister = PtmControlRegister | BIT1; // Enable PTM
  825. }
  826. PtmControlRegister = PtmControlRegister | (PtmCapabilityRegister & 0xFF00); // Programm Local Clock Granularity
  827. } else {
  828. PtmControlRegister = PtmControlRegister & (UINT16)(~(BIT0 | BIT1)); // Disable Clock Power Management
  829. }
  830. PciSegmentWrite16(DeviceBaseAddress + CapHeaderOffset + 0x08, PtmControlRegister);
  831. }
  832. }
  833. }
  834. VOID
  835. ConfigureTbtPm (
  836. IN UINTN RpSegment,
  837. IN UINTN RpBus,
  838. IN UINTN RpDevice,
  839. IN UINTN RpFunction,
  840. IN UINT8 Configuration // 1- Clk Request , 2- PTM ,
  841. )
  842. {
  843. UINT8 Bus;
  844. UINT8 Dev;
  845. UINT8 Fun;
  846. UINT8 MinBus;
  847. UINT8 MaxBus;
  848. UINT16 DeviceId;
  849. UINT64 DeviceBaseAddress;
  850. MinBus = 0;
  851. MaxBus = 0;
  852. if ((Configuration != 1) && (Configuration != 2)) {
  853. return;
  854. }
  855. MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
  856. MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
  857. DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
  858. if (!(IsTbtHostRouter (DeviceId))) {
  859. return;
  860. }
  861. TbtSegment = (UINT8)RpSegment;
  862. //
  863. // Enumerate all the bridges and devices which are available on TBT host controller
  864. //
  865. for (Bus = MaxBus; Bus >= MinBus; --Bus) {
  866. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  867. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  868. //
  869. // Check for Device availability
  870. //
  871. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  872. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  873. if (Fun == 0) {
  874. //
  875. // IF Fun is zero, stop enumerating other functions of the particular bridge
  876. //
  877. break;
  878. }
  879. //
  880. // otherwise, just skip checking for CLKREQ support
  881. //
  882. continue;
  883. }
  884. switch (Configuration) {
  885. case 1:
  886. TbtProgramClkReq (Bus, Dev, Fun, (UINT8) mTbtNvsAreaPtr->TbtSetClkReq);
  887. break;
  888. case 2:
  889. TbtProgramPtm (Bus, Dev, Fun, (UINT8) mTbtNvsAreaPtr->TbtPtm, FALSE);
  890. TbtProgramPtm((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, (UINT8) mTbtNvsAreaPtr->TbtPtm, TRUE);
  891. break;
  892. default:
  893. break;
  894. }
  895. } //Fun
  896. } // Dev
  897. } // Bus
  898. }
  899. /**
  900. 1) Check LTR support in device capabilities 2 register (bit 11).
  901. 2) If supported enable LTR in device control 2 register (bit 10).
  902. **/
  903. VOID
  904. TbtProgramLtr (
  905. IN UINT8 Bus,
  906. IN UINT8 Device,
  907. IN UINT8 Function,
  908. IN UINT8 LtrSetup
  909. )
  910. {
  911. UINT64 DeviceBaseAddress;
  912. UINT8 CapHeaderOffset;
  913. UINT16 Data16;
  914. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Device, Function, 0);
  915. CapHeaderOffset = PcieFindCapId (TbtSegment, Bus, Device, Function, 0x10);
  916. //
  917. // Check if LTR# is supported
  918. //
  919. if ((PciSegmentRead32 (DeviceBaseAddress + CapHeaderOffset + 0x24) & BIT11) != 0) {
  920. Data16 = PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 0x028);
  921. if (LtrSetup) {
  922. Data16 = Data16 | BIT10; // LTR Mechanism Enable
  923. } else {
  924. Data16 = Data16 & (UINT16)(~BIT10); // LTR Mechanism Disable
  925. }
  926. PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffset + 0x028, Data16);
  927. }
  928. }
  929. VOID
  930. ConfigureLtr (
  931. IN UINTN RpSegment,
  932. IN UINTN RpBus,
  933. IN UINTN RpDevice,
  934. IN UINTN RpFunction
  935. )
  936. {
  937. UINT8 Bus;
  938. UINT8 Dev;
  939. UINT8 Fun;
  940. UINT8 MinBus;
  941. UINT8 MaxBus;
  942. UINT16 DeviceId;
  943. UINT64 DeviceBaseAddress;
  944. MinBus = 0;
  945. MaxBus = 0;
  946. MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
  947. MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
  948. DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
  949. if (!(IsTbtHostRouter (DeviceId))) {
  950. return;
  951. }
  952. TbtSegment = (UINT8)RpSegment;
  953. //
  954. // Enumerate all the bridges and devices which are available on TBT host controller
  955. //
  956. for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
  957. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  958. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  959. //
  960. // Check for Device availability
  961. //
  962. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  963. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  964. if (Fun == 0) {
  965. //
  966. // IF Fun is zero, stop enumerating other functions of the particular bridge
  967. //
  968. break;
  969. }
  970. //
  971. // otherwise, just skip checking for LTR support
  972. //
  973. continue;
  974. }
  975. TbtProgramLtr (Bus, Dev, Fun, (UINT8) mTbtNvsAreaPtr->TbtLtr);
  976. } //Fun
  977. } // Dev
  978. } // Bus
  979. TbtProgramLtr ((UINT8) RpBus, (UINT8) RpDevice, (UINT8) RpFunction, (UINT8) mTbtNvsAreaPtr->TbtLtr);
  980. }
  981. /*
  982. US ports and endpoints which declare support must also have the LTR capability structure (cap ID 18h).
  983. In this structure you need to enter the max snoop latency and max non-snoop latency in accordance with the format specified in the PCIe spec.
  984. The latency value itself is platform specific so you'll need to get it from the platform architect or whatever.
  985. */
  986. VOID
  987. ThunderboltGetLatencyLtr (
  988. VOID
  989. )
  990. {
  991. PCH_SERIES PchSeries;
  992. PchSeries = GetPchSeries ();
  993. if(gCurrentDiscreteTbtRootPortType == DTBT_TYPE_PEG) {
  994. // PEG selector
  995. TbtLtrMaxSnoopLatency = LTR_MAX_SNOOP_LATENCY_VALUE;
  996. TbtLtrMaxNoSnoopLatency = LTR_MAX_NON_SNOOP_LATENCY_VALUE;
  997. } else if (gCurrentDiscreteTbtRootPortType == DTBT_TYPE_PCH) {
  998. // PCH selector
  999. if (PchSeries == PchLp) {
  1000. TbtLtrMaxSnoopLatency = 0x1003;
  1001. TbtLtrMaxNoSnoopLatency = 0x1003;
  1002. }
  1003. if (PchSeries == PchH) {
  1004. TbtLtrMaxSnoopLatency = 0x0846;
  1005. TbtLtrMaxNoSnoopLatency = 0x0846;
  1006. }
  1007. }
  1008. }
  1009. VOID
  1010. SetLatencyLtr (
  1011. IN UINT8 Bus,
  1012. IN UINT8 Dev,
  1013. IN UINT8 Fun,
  1014. IN UINT16 CapHeaderOffsetExtd,
  1015. IN UINT16 LtrMaxSnoopLatency,
  1016. IN UINT16 LtrMaxNoSnoopLatency
  1017. )
  1018. {
  1019. UINT64 DeviceBaseAddress;
  1020. if(CapHeaderOffsetExtd == 0) {
  1021. return;
  1022. }
  1023. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  1024. PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffsetExtd + 0x004, LtrMaxSnoopLatency);
  1025. PciSegmentWrite16 (DeviceBaseAddress + CapHeaderOffsetExtd + 0x006, LtrMaxNoSnoopLatency);
  1026. }
  1027. VOID
  1028. ThunderboltSetLatencyLtr (
  1029. IN UINTN RpSegment,
  1030. IN UINTN RpBus,
  1031. IN UINTN RpDevice,
  1032. IN UINTN RpFunction
  1033. )
  1034. {
  1035. UINT8 Bus;
  1036. UINT8 Dev;
  1037. UINT8 Fun;
  1038. UINT8 MinBus;
  1039. UINT8 MaxBus;
  1040. UINT16 DeviceId;
  1041. UINT64 DeviceBaseAddress;
  1042. UINT8 CapHeaderOffsetStd;
  1043. UINT16 CapHeaderOffsetExtd;
  1044. UINT16 DevicePortType;
  1045. MinBus = 0;
  1046. MaxBus = 0;
  1047. MinBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET));
  1048. MaxBus = PciSegmentRead8 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, RpBus, RpDevice, RpFunction, PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET));
  1049. DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (RpSegment, MinBus, 0x00, 0x00, PCI_DEVICE_ID_OFFSET));
  1050. if (!(IsTbtHostRouter (DeviceId))) {
  1051. return;
  1052. }
  1053. TbtSegment = (UINT8)RpSegment;
  1054. for (Bus = MinBus; Bus <= MaxBus; ++Bus) {
  1055. for (Dev = 0; Dev <= PCI_MAX_DEVICE; ++Dev) {
  1056. for (Fun = 0; Fun <= PCI_MAX_FUNC; ++Fun) {
  1057. //
  1058. // Check for Device availability
  1059. //
  1060. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, Bus, Dev, Fun, 0);
  1061. if (PciSegmentRead16 (DeviceBaseAddress + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  1062. //
  1063. // Device not present
  1064. //
  1065. continue;
  1066. }
  1067. CapHeaderOffsetStd = PcieFindCapId (TbtSegment, Bus, Dev, Fun, 0x10);
  1068. DevicePortType = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffsetStd + 0x002) >> 4) & 0xF;
  1069. CapHeaderOffsetExtd = PcieFindExtendedCapId (Bus, Dev, Fun, 0x0018);
  1070. switch (DevicePortType) {
  1071. case 0:
  1072. //
  1073. // PCI Express Endpoint
  1074. //
  1075. SetLatencyLtr (Bus, Dev, Fun, CapHeaderOffsetExtd, TbtLtrMaxSnoopLatency, TbtLtrMaxNoSnoopLatency);
  1076. break;
  1077. case 1:
  1078. //
  1079. // Legacy PCI Express Endpoint
  1080. //
  1081. SetLatencyLtr (Bus, Dev, Fun, CapHeaderOffsetExtd, TbtLtrMaxSnoopLatency, TbtLtrMaxNoSnoopLatency);
  1082. break;
  1083. case 4:
  1084. //
  1085. // Root Port of PCI Express Root Complex
  1086. //
  1087. // Do-nothing
  1088. break;
  1089. case 5:
  1090. //
  1091. // Upstream Port of PCI Express Switch
  1092. //
  1093. SetLatencyLtr (Bus, Dev, Fun, CapHeaderOffsetExtd, TbtLtrMaxSnoopLatency, TbtLtrMaxNoSnoopLatency);
  1094. break;
  1095. case 6:
  1096. //
  1097. // Downstream Port of PCI Express Switch
  1098. //
  1099. // Do-nothing
  1100. break;
  1101. case 7:
  1102. //
  1103. // PCI Express to PCI/PCI-X Bridge
  1104. //
  1105. // Do-nothing
  1106. break;
  1107. case 8:
  1108. //
  1109. // PCI/PCI-X to PCI Express Bridge
  1110. //
  1111. // Do-nothing
  1112. break;
  1113. case 9:
  1114. //
  1115. // Root Complex Integrated Endpoint
  1116. //
  1117. // Do-nothing
  1118. break;
  1119. case 10:
  1120. //
  1121. // Root Complex Event Collector
  1122. //
  1123. // Do-nothing
  1124. break;
  1125. default:
  1126. break;
  1127. }
  1128. //
  1129. // switch(DevicePortType)
  1130. //
  1131. }
  1132. //
  1133. // Fun
  1134. //
  1135. }
  1136. //
  1137. // Dev
  1138. //
  1139. }
  1140. //
  1141. // Bus
  1142. //
  1143. }
  1144. static
  1145. VOID
  1146. Stall (
  1147. UINTN Usec
  1148. )
  1149. {
  1150. UINTN Index;
  1151. UINT32 Data32;
  1152. UINT32 PrevData;
  1153. UINTN Counter;
  1154. Counter = (UINTN) ((Usec * 10) / 3);
  1155. //
  1156. // Call WaitForTick for Counter + 1 ticks to try to guarantee Counter tick
  1157. // periods, thus attempting to ensure Microseconds of stall time.
  1158. //
  1159. if (Counter != 0) {
  1160. PrevData = IoRead32 (PcdGet16 (PcdAcpiBaseAddress) + R_PCH_ACPI_PM1_TMR);
  1161. for (Index = 0; Index < Counter;) {
  1162. Data32 = IoRead32 (PcdGet16 (PcdAcpiBaseAddress) + R_PCH_ACPI_PM1_TMR);
  1163. if (Data32 < PrevData) {
  1164. //
  1165. // Reset if there is a overlap
  1166. //
  1167. PrevData = Data32;
  1168. continue;
  1169. }
  1170. Index += (Data32 - PrevData);
  1171. PrevData = Data32;
  1172. }
  1173. }
  1174. return ;
  1175. }
  1176. /**
  1177. Called during Sx entry, initates TbtSetPcie2TbtCommand HandShake to set GO2SX_NO_WAKE
  1178. for Tbt devices if WakeupSupport is not present.
  1179. @param[in] DispatchHandle - The unique handle assigned to this handler by SmiHandlerRegister().
  1180. @param[in] DispatchContext - Points to an optional handler context which was specified when the
  1181. handler was registered.
  1182. @param[in, out] CommBuffer - A pointer to a collection of data in memory that will
  1183. be conveyed from a non-SMM environment into an SMM environment.
  1184. @param[in, out] CommBufferSize - The size of the CommBuffer.
  1185. @retval EFI_SUCCESS - The interrupt was handled successfully.
  1186. **/
  1187. EFI_STATUS
  1188. EFIAPI
  1189. SxDTbtEntryCallback (
  1190. IN EFI_HANDLE DispatchHandle,
  1191. IN CONST VOID *DispatchContext,
  1192. IN OUT VOID *CommBuffer OPTIONAL,
  1193. IN UINTN *CommBufferSize OPTIONAL
  1194. )
  1195. {
  1196. UINT16 DeviceId;
  1197. UINT8 CableConnected;
  1198. UINT8 RootportSelected;
  1199. UINT8 HoustRouteBus;
  1200. volatile UINT32 *PowerState;
  1201. UINT32 PowerStatePrev;
  1202. BOOLEAN SecSubBusAssigned;
  1203. UINT64 DeviceBaseAddress;
  1204. UINT8 CapHeaderOffset;
  1205. UINTN RpDev;
  1206. UINTN RpFunc;
  1207. EFI_STATUS Status;
  1208. UINT32 Timeout;
  1209. UINT32 RegisterValue;
  1210. UINT64 Tbt2Pcie;
  1211. UINTN Index;
  1212. UINT32 TbtCioPlugEventGpioNo;
  1213. UINT32 TbtFrcPwrGpioNo;
  1214. UINT8 TbtFrcPwrGpioLevel;
  1215. UINT32 TbtPcieRstGpioNo;
  1216. UINT8 TbtPcieRstGpioLevel;
  1217. EFI_SMM_SX_REGISTER_CONTEXT *EntryDispatchContext;
  1218. CableConnected = 0;
  1219. HoustRouteBus = 3;
  1220. SecSubBusAssigned = FALSE;
  1221. Timeout = 600;
  1222. RootportSelected = 0;
  1223. TbtCioPlugEventGpioNo = 0;
  1224. TbtFrcPwrGpioNo = 0;
  1225. TbtFrcPwrGpioLevel = 0;
  1226. TbtPcieRstGpioNo = 0;
  1227. TbtPcieRstGpioLevel = 0;
  1228. Index = 0;
  1229. EntryDispatchContext = (EFI_SMM_SX_REGISTER_CONTEXT*) DispatchContext;
  1230. // CableConnected = GetTbtHostRouterStatus ();
  1231. //SaveTbtHostRouterStatus (CableConnected & 0xF0);
  1232. //
  1233. // Get the Power State and Save
  1234. //
  1235. if (((mTbtNvsAreaPtr->DTbtControllerEn0 == 0) && (Index == 0))) {
  1236. RootportSelected = mTbtNvsAreaPtr->RootportSelected0;
  1237. TbtCioPlugEventGpioNo = mTbtNvsAreaPtr->TbtCioPlugEventGpioNo0;
  1238. TbtFrcPwrGpioNo = mTbtNvsAreaPtr->TbtFrcPwrGpioNo0;
  1239. TbtFrcPwrGpioLevel = mTbtNvsAreaPtr->TbtFrcPwrGpioLevel0;
  1240. TbtPcieRstGpioNo = mTbtNvsAreaPtr->TbtPcieRstGpioNo0;
  1241. TbtPcieRstGpioLevel = mTbtNvsAreaPtr->TbtPcieRstGpioLevel0;
  1242. }
  1243. Status = GetDTbtRpDevFun (gCurrentDiscreteTbtRootPortType, RootportSelected - 1, &RpDev, &RpFunc);
  1244. ASSERT_EFI_ERROR (Status);
  1245. CapHeaderOffset = PcieFindCapId (TbtSegment, 0x00, (UINT8)RpDev, (UINT8)RpFunc, 0x01);
  1246. DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (TbtSegment, 0x00, (UINT32)RpDev, (UINT32)RpFunc, 0);
  1247. PowerState = &*((volatile UINT32 *) (mPciExpressBaseAddress + DeviceBaseAddress + CapHeaderOffset + 4)); //PMCSR
  1248. PowerStatePrev = *PowerState;
  1249. *PowerState &= 0xFFFFFFFC;
  1250. HoustRouteBus = PciSegmentRead8 (DeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET);
  1251. //
  1252. // Check the Subordinate bus .If it is Zero ,assign temporary bus to
  1253. // find the device presence .
  1254. //
  1255. if (HoustRouteBus == 0) {
  1256. PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0xF0);
  1257. PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0xF0);
  1258. HoustRouteBus = 0xF0;
  1259. SecSubBusAssigned = TRUE;
  1260. }
  1261. //
  1262. // Clear Interrupt capability of TBT CIO Plug Event Pin to make sure no SCI is getting generated,
  1263. // This GPIO will be reprogrammed while resuming as part of Platform GPIO Programming.
  1264. //
  1265. GpioSetPadInterruptConfig (TbtCioPlugEventGpioNo, GpioIntDis);
  1266. //
  1267. // Read the TBT Host router DeviceID
  1268. //
  1269. DeviceId = PciSegmentRead16 (PCI_SEGMENT_LIB_ADDRESS (TbtSegment, HoustRouteBus, 0, 0, PCI_DEVICE_ID_OFFSET));
  1270. //
  1271. // Check For HostRouter Presence
  1272. //
  1273. if (IsTbtHostRouter (DeviceId)) {
  1274. // CableConnected = GetTbtHostRouterStatus ();
  1275. if (!((CableConnected & (DTBT_SAVE_STATE_OFFSET << Index)) == (DTBT_SAVE_STATE_OFFSET << Index))) {
  1276. CableConnected = CableConnected | (DTBT_SAVE_STATE_OFFSET << Index);
  1277. // SaveTbtHostRouterStatus (CableConnected);
  1278. }
  1279. }
  1280. //
  1281. // Check value of Tbt2Pcie reg, if Tbt is not present, bios needs to apply force power prior to sending mailbox command
  1282. //
  1283. GET_TBT2PCIE_REGISTER_ADDRESS(TbtSegment, HoustRouteBus, 0x00, 0x00, Tbt2Pcie)
  1284. RegisterValue = PciSegmentRead32 (Tbt2Pcie);
  1285. if (0xFFFFFFFF == RegisterValue) {
  1286. GpioWrite (TbtFrcPwrGpioNo,TbtFrcPwrGpioLevel);
  1287. while (Timeout -- > 0) {
  1288. RegisterValue = PciSegmentRead32 (Tbt2Pcie);
  1289. if (0xFFFFFFFF != RegisterValue) {
  1290. break;
  1291. }
  1292. Stall(1* (UINTN)1000);
  1293. }
  1294. //
  1295. // Before entering Sx state BIOS should execute GO2SX/NO_WAKE mailbox command for AIC.
  1296. // However BIOS shall not execute go2sx mailbox command on S5/reboot cycle.
  1297. //
  1298. if( (EntryDispatchContext->Type == SxS3) || (EntryDispatchContext->Type == SxS4))
  1299. {
  1300. if(!mTbtNvsAreaPtr->TbtWakeupSupport) {
  1301. //Wake Disabled, GO2SX_NO_WAKE Command
  1302. TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX_NO_WAKE, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
  1303. } else {
  1304. //Wake Enabled, GO2SX Command
  1305. TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
  1306. }
  1307. }
  1308. if (mTbtNvsAreaPtr->TbtFrcPwrEn == 0) {
  1309. GpioWrite (TbtFrcPwrGpioNo,!(TbtFrcPwrGpioLevel));
  1310. }
  1311. } else {
  1312. //
  1313. // Before entering Sx state BIOS should execute GO2SX/NO_WAKE mailbox command for AIC.
  1314. // However BIOS shall not execute go2sx mailbox command on S5/reboot cycle.
  1315. //
  1316. if( (EntryDispatchContext->Type == SxS3) || (EntryDispatchContext->Type == SxS4))
  1317. {
  1318. if(!mTbtNvsAreaPtr->TbtWakeupSupport) {
  1319. //Wake Disabled, GO2SX_NO_WAKE Command
  1320. TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX_NO_WAKE, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
  1321. } else {
  1322. //Wake Enabled, GO2SX Command
  1323. TbtSetPcie2TbtCommand (PCIE2TBT_GO2SX, HoustRouteBus, 0, 0, TBT_5S_TIMEOUT);
  1324. }
  1325. }
  1326. }
  1327. *PowerState = PowerStatePrev;
  1328. //
  1329. // Restore the bus number in case we assigned temporarily
  1330. //
  1331. if (SecSubBusAssigned) {
  1332. PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SECONDARY_BUS_REGISTER_OFFSET, 0x00);
  1333. PciSegmentWrite8 (DeviceBaseAddress + PCI_BRIDGE_SUBORDINATE_BUS_REGISTER_OFFSET, 0x00);
  1334. }
  1335. if (gDTbtPcieRstSupport) {
  1336. GpioWrite (TbtPcieRstGpioNo,TbtPcieRstGpioLevel);
  1337. }
  1338. return EFI_SUCCESS;
  1339. }
  1340. VOID
  1341. ThunderboltSwSmiCallback (
  1342. IN UINT8 Type
  1343. )
  1344. {
  1345. UINT8 ThunderboltSmiFunction;
  1346. DEBUG ((DEBUG_INFO, "ThunderboltSwSmiCallback Entry\n"));
  1347. ThunderboltSmiFunction = mTbtNvsAreaPtr->ThunderboltSmiFunction;
  1348. DEBUG ((DEBUG_INFO, "ThunderboltSwSmiCallback. ThunderboltSmiFunction=%d\n", ThunderboltSmiFunction));
  1349. if (Type == DTBT_CONTROLLER) {
  1350. gCurrentDiscreteTbtRootPort = mTbtNvsAreaPtr->CurrentDiscreteTbtRootPort;
  1351. gCurrentDiscreteTbtRootPortType = mTbtNvsAreaPtr->CurrentDiscreteTbtRootPortType;
  1352. }
  1353. switch (ThunderboltSmiFunction) {
  1354. case 21:
  1355. ThunderboltCallback (Type);
  1356. break;
  1357. case 22:
  1358. TbtDisablePCIDevicesAndBridges (Type);
  1359. break;
  1360. case 23:
  1361. ConfigureTbtAspm (Type, (UINT16) 0x02);
  1362. break;
  1363. case 24:
  1364. ConfigureTbtAspm (Type, (UINT16) 0x01);
  1365. break;
  1366. default:
  1367. break;
  1368. }
  1369. DEBUG ((DEBUG_INFO, "ThunderboltSwSmiCallback Exit.\n"));
  1370. }
  1371. STATIC
  1372. EFI_STATUS
  1373. EFIAPI
  1374. DiscreteThunderboltSwSmiCallback (
  1375. IN EFI_HANDLE DispatchHandle,
  1376. IN CONST VOID *DispatchContext,
  1377. IN OUT VOID *CommBuffer OPTIONAL,
  1378. IN UINTN *CommBufferSize OPTIONAL
  1379. )
  1380. {
  1381. ThunderboltSwSmiCallback(DTBT_CONTROLLER);
  1382. return EFI_SUCCESS;
  1383. }
  1384. EFI_STATUS
  1385. TbtRegisterHandlers (
  1386. IN BOOLEAN Type
  1387. )
  1388. {
  1389. EFI_STATUS Status;
  1390. UINTN SmiInputValue;
  1391. EFI_SMM_HANDLER_ENTRY_POINT2 SxHandler;
  1392. EFI_SMM_HANDLER_ENTRY_POINT2 SwHandler;
  1393. EFI_SMM_SX_DISPATCH2_PROTOCOL *SxDispatchProtocol;
  1394. EFI_SMM_SW_DISPATCH2_PROTOCOL *SwDispatch;
  1395. EFI_SMM_SX_REGISTER_CONTEXT EntryDispatchContext;
  1396. EFI_SMM_SW_REGISTER_CONTEXT SwContext;
  1397. EFI_HANDLE SwDispatchHandle;
  1398. EFI_HANDLE S3DispatchHandle;
  1399. EFI_HANDLE S4DispatchHandle;
  1400. EFI_HANDLE S5DispatchHandle;
  1401. Status = EFI_UNSUPPORTED;
  1402. if(Type == DTBT_CONTROLLER) {
  1403. SxHandler = SxDTbtEntryCallback;
  1404. SwHandler = DiscreteThunderboltSwSmiCallback;
  1405. SmiInputValue = PcdGet8 (PcdSwSmiDTbtEnumerate);
  1406. gDTbtPcieRstSupport = gTbtInfoHob->DTbtCommonConfig.PcieRstSupport;
  1407. Status = EFI_SUCCESS;
  1408. }
  1409. if (EFI_ERROR (Status)) {
  1410. return Status;
  1411. }
  1412. SwDispatchHandle = NULL;
  1413. S3DispatchHandle = NULL;
  1414. S4DispatchHandle = NULL;
  1415. S5DispatchHandle = NULL;
  1416. Status = gSmst->SmmLocateProtocol (
  1417. &gEfiSmmSxDispatch2ProtocolGuid,
  1418. NULL,
  1419. (VOID **) &SxDispatchProtocol
  1420. );
  1421. ASSERT_EFI_ERROR (Status);
  1422. //
  1423. // Register S3 entry phase call back function
  1424. //
  1425. EntryDispatchContext.Type = SxS3;
  1426. EntryDispatchContext.Phase = SxEntry;
  1427. Status = SxDispatchProtocol->Register (
  1428. SxDispatchProtocol,
  1429. SxHandler,
  1430. &EntryDispatchContext,
  1431. &S3DispatchHandle
  1432. );
  1433. ASSERT_EFI_ERROR (Status);
  1434. //
  1435. // Register S4 entry phase call back function
  1436. //
  1437. EntryDispatchContext.Type = SxS4;
  1438. EntryDispatchContext.Phase = SxEntry;
  1439. Status = SxDispatchProtocol->Register (
  1440. SxDispatchProtocol,
  1441. SxHandler,
  1442. &EntryDispatchContext,
  1443. &S4DispatchHandle
  1444. );
  1445. ASSERT_EFI_ERROR (Status);
  1446. //
  1447. // Register S5 entry phase call back function
  1448. //
  1449. EntryDispatchContext.Type = SxS5;
  1450. EntryDispatchContext.Phase = SxEntry;
  1451. Status = SxDispatchProtocol->Register (
  1452. SxDispatchProtocol,
  1453. SxHandler,
  1454. &EntryDispatchContext,
  1455. &S5DispatchHandle
  1456. );
  1457. ASSERT_EFI_ERROR (Status);
  1458. //
  1459. // Locate the SMM SW dispatch protocol
  1460. //
  1461. Status = gSmst->SmmLocateProtocol (
  1462. &gEfiSmmSwDispatch2ProtocolGuid,
  1463. NULL,
  1464. (VOID **) &SwDispatch
  1465. );
  1466. ASSERT_EFI_ERROR (Status);
  1467. //
  1468. // Register SWSMI handler
  1469. //
  1470. SwContext.SwSmiInputValue = SmiInputValue;
  1471. Status = SwDispatch->Register (
  1472. SwDispatch,
  1473. SwHandler,
  1474. &SwContext,
  1475. &SwDispatchHandle
  1476. );
  1477. ASSERT_EFI_ERROR (Status);
  1478. return Status;
  1479. }
  1480. EFI_STATUS
  1481. InSmmFunction (
  1482. IN EFI_HANDLE ImageHandle,
  1483. IN EFI_SYSTEM_TABLE *SystemTable
  1484. )
  1485. {
  1486. EFI_STATUS Status;
  1487. Status = EFI_SUCCESS;
  1488. Status = TbtRegisterHandlers(DTBT_CONTROLLER);
  1489. return Status;
  1490. }
  1491. EFI_STATUS
  1492. EFIAPI
  1493. TbtSmmEntryPoint (
  1494. IN EFI_HANDLE ImageHandle,
  1495. IN EFI_SYSTEM_TABLE *SystemTable
  1496. )
  1497. {
  1498. TBT_NVS_AREA_PROTOCOL *TbtNvsAreaProtocol;
  1499. EFI_STATUS Status;
  1500. DEBUG ((DEBUG_INFO, "TbtSmmEntryPoint\n"));
  1501. mPciExpressBaseAddress = PcdGet64 (PcdPciExpressBaseAddress);
  1502. //
  1503. // Locate Tbt shared data area
  1504. //
  1505. Status = gBS->LocateProtocol (&gTbtNvsAreaProtocolGuid, NULL, (VOID **) &TbtNvsAreaProtocol);
  1506. ASSERT_EFI_ERROR (Status);
  1507. mTbtNvsAreaPtr = TbtNvsAreaProtocol->Area;
  1508. //
  1509. // Get TBT INFO HOB
  1510. //
  1511. gTbtInfoHob = (TBT_INFO_HOB *) GetFirstGuidHob (&gTbtInfoHobGuid);
  1512. if (gTbtInfoHob == NULL) {
  1513. return EFI_NOT_FOUND;
  1514. }
  1515. return InSmmFunction (ImageHandle, SystemTable);
  1516. }
  1517. VOID
  1518. EndOfThunderboltCallback (
  1519. IN UINTN RpSegment,
  1520. IN UINTN RpBus,
  1521. IN UINTN RpDevice,
  1522. IN UINTN RpFunction
  1523. )
  1524. {
  1525. if(mTbtNvsAreaPtr->TbtL1SubStates != 0) {
  1526. ThunderboltEnableL1Sub (mTbtNvsAreaPtr->TbtL1SubStates, RpSegment, RpBus, RpDevice, RpFunction);
  1527. }
  1528. ConfigureTbtPm(RpSegment, RpBus, RpDevice, RpFunction, 1);
  1529. if (!mTbtNvsAreaPtr->TbtAspm) { //Aspm disable case
  1530. ThunderboltDisableAspmWithoutLtr (RpSegment, RpBus, RpDevice, RpFunction);
  1531. } else { //Aspm enable case
  1532. ThunderboltEnableAspmWithoutLtr ((UINT16)mTbtNvsAreaPtr->TbtAspm, RpSegment, RpBus, RpDevice, RpFunction);
  1533. }
  1534. if (mTbtNvsAreaPtr->TbtLtr) {
  1535. ThunderboltGetLatencyLtr ();
  1536. ThunderboltSetLatencyLtr (RpSegment, RpBus, RpDevice, RpFunction);
  1537. }
  1538. ConfigureLtr (RpSegment, RpBus, RpDevice, RpFunction);
  1539. ConfigureTbtPm(RpSegment, RpBus, RpDevice, RpFunction, 2);
  1540. } // EndOfThunderboltCallback
  1541. VOID
  1542. ConfigureTbtAspm (
  1543. IN UINT8 Type,
  1544. IN UINT16 Aspm
  1545. )
  1546. {
  1547. UINTN RpSegment = 0;
  1548. UINTN RpBus = 0;
  1549. UINTN RpDevice;
  1550. UINTN RpFunction;
  1551. if(Type == DTBT_CONTROLLER) {
  1552. if (gCurrentDiscreteTbtRootPort == 0) {
  1553. return;
  1554. }
  1555. GetDTbtRpDevFun(DTBT_CONTROLLER, gCurrentDiscreteTbtRootPort - 1, &RpDevice, &RpFunction);
  1556. ConfigureTbtPm (RpSegment, RpBus, RpDevice, RpFunction, 1);
  1557. if (!mTbtNvsAreaPtr->TbtAspm) { //Aspm disable case
  1558. ThunderboltDisableAspmWithoutLtr (RpSegment, RpBus, RpDevice, RpFunction);
  1559. } else { //Aspm enable case
  1560. ThunderboltEnableAspmWithoutLtr ((UINT16) Aspm, RpSegment, RpBus, RpDevice, RpFunction);
  1561. }
  1562. if (mTbtNvsAreaPtr->TbtLtr) {
  1563. ThunderboltGetLatencyLtr ();
  1564. ThunderboltSetLatencyLtr (RpSegment, RpBus, RpDevice, RpFunction);
  1565. }
  1566. ConfigureLtr (RpSegment, RpBus, RpDevice, RpFunction);
  1567. } // EndOfThunderboltCallback
  1568. }