TbtSmm.c 54 KB

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