PcieCore.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508
  1. /** @file
  2. Copyright (c) 2020 - 2023, Ampere Computing LLC. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <PiDxe.h>
  6. #include <Guid/PlatformInfoHob.h>
  7. #include <Guid/RootComplexInfoHob.h>
  8. #include <IndustryStandard/Pci.h>
  9. #include <Library/ArmGenericTimerCounterLib.h>
  10. #include <Library/BaseLib.h>
  11. #include <Library/BaseMemoryLib.h>
  12. #include <Library/BoardPcieLib.h>
  13. #include <Library/DebugLib.h>
  14. #include <Library/HobLib.h>
  15. #include <Library/IoLib.h>
  16. #include <Library/PciePhyLib.h>
  17. #include <Library/SystemFirmwareInterfaceLib.h>
  18. #include <Library/TimerLib.h>
  19. #include "PcieCore.h"
  20. VOID
  21. EnableDbiAccess (
  22. AC01_ROOT_COMPLEX *RootComplex,
  23. UINT32 PcieIndex,
  24. BOOLEAN EnableDbi
  25. );
  26. BOOLEAN
  27. EndpointCfgReady (
  28. IN AC01_ROOT_COMPLEX *RootComplex,
  29. IN UINT8 PcieIndex,
  30. IN UINT32 Timeout
  31. );
  32. BOOLEAN
  33. PcieLinkUpCheck (
  34. IN AC01_PCIE_CONTROLLER *Pcie
  35. );
  36. /**
  37. Return the next extended capability base address
  38. @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
  39. @param PcieIndex PCIe controller index
  40. @param IsRootComplex TRUE: Checking RootComplex configuration space
  41. FALSE: Checking EP configuration space
  42. @param ExtCapabilityId
  43. **/
  44. PHYSICAL_ADDRESS
  45. GetCapabilityBase (
  46. IN AC01_ROOT_COMPLEX *RootComplex,
  47. IN UINT8 PcieIndex,
  48. IN BOOLEAN IsRootComplex,
  49. IN UINT16 ExtCapabilityId
  50. )
  51. {
  52. BOOLEAN IsExtCapability = FALSE;
  53. PHYSICAL_ADDRESS CfgBase;
  54. PHYSICAL_ADDRESS Ret = 0;
  55. PHYSICAL_ADDRESS RootComplexCfgBase;
  56. UINT32 CapabilityId;
  57. UINT32 NextCapabilityPtr;
  58. UINT32 Val;
  59. UINT32 RestoreVal;
  60. RootComplexCfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  61. if (!IsRootComplex) {
  62. // Allow programming to config space
  63. EnableDbiAccess (RootComplex, PcieIndex, TRUE);
  64. Val = MmioRead32 (RootComplexCfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG);
  65. RestoreVal = Val;
  66. Val = SUB_BUS_SET (Val, DEFAULT_SUB_BUS);
  67. Val = SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum);
  68. Val = PRIM_BUS_SET (Val, 0x0);
  69. MmioWrite32 (RootComplexCfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG, Val);
  70. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
  71. if (!EndpointCfgReady (RootComplex, PcieIndex, EP_LINKUP_TIMEOUT)) {
  72. goto _CheckCapEnd;
  73. }
  74. } else {
  75. CfgBase = RootComplexCfgBase;
  76. }
  77. // Check if device provide capability
  78. Val = MmioRead32 (CfgBase + PCI_COMMAND_OFFSET);
  79. Val = GET_HIGH_16_BITS (Val); /* Status */
  80. if (!(Val & EFI_PCI_STATUS_CAPABILITY)) {
  81. goto _CheckCapEnd;
  82. }
  83. Val = MmioRead32 (CfgBase + TYPE1_CAP_PTR_REG);
  84. NextCapabilityPtr = GET_LOW_8_BITS (Val);
  85. // Loop untill desired capability is found else return 0
  86. while (1) {
  87. if ((NextCapabilityPtr & WORD_ALIGN_MASK) != 0) {
  88. // Not alignment, just return
  89. Ret = 0;
  90. goto _CheckCapEnd;
  91. }
  92. Val = MmioRead32 (CfgBase + NextCapabilityPtr);
  93. if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) {
  94. CapabilityId = GET_LOW_8_BITS (Val);
  95. } else {
  96. CapabilityId = GET_LOW_16_BITS (Val);
  97. }
  98. if (CapabilityId == ExtCapabilityId) {
  99. Ret = (CfgBase + NextCapabilityPtr);
  100. goto _CheckCapEnd;
  101. }
  102. if (NextCapabilityPtr < EXT_CAPABILITY_START_BASE) {
  103. NextCapabilityPtr = GET_CAPABILITY_PTR (Val);
  104. } else {
  105. NextCapabilityPtr = GET_EXT_CAPABILITY_PTR (Val);
  106. }
  107. if ((NextCapabilityPtr == 0) && !IsExtCapability) {
  108. IsExtCapability = TRUE;
  109. NextCapabilityPtr = EXT_CAPABILITY_START_BASE;
  110. }
  111. if ((NextCapabilityPtr == 0) && IsExtCapability) {
  112. Ret = 0;
  113. goto _CheckCapEnd;
  114. }
  115. }
  116. _CheckCapEnd:
  117. if (!IsRootComplex) {
  118. MmioWrite32 (RootComplexCfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG, RestoreVal);
  119. // Disable programming to config space
  120. EnableDbiAccess (RootComplex, PcieIndex, FALSE);
  121. }
  122. return Ret;
  123. }
  124. /**
  125. Configure equalization settings for Gen3 and Gen4
  126. @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
  127. @param PcieIndex PCIe controller index
  128. **/
  129. STATIC
  130. VOID
  131. ConfigureEqualization (
  132. IN AC01_ROOT_COMPLEX *RootComplex,
  133. IN UINT8 PcieIndex
  134. )
  135. {
  136. PHYSICAL_ADDRESS CfgBase;
  137. PHYSICAL_ADDRESS Gen3RelatedAddr;
  138. PHYSICAL_ADDRESS Gen3EqControlAddr;
  139. UINT32 Val;
  140. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  141. //
  142. // Gen3 and Gen4 EQ process use the same setting registers which are
  143. // GEN3_RELATED_OFF and GEN3_EQ_CONTROL_OFF. Both are shadow registers
  144. // and controlled by GEN3_RELATED_OFF[25:24].
  145. //
  146. Gen3RelatedAddr = CfgBase + GEN3_RELATED_OFF;
  147. Gen3EqControlAddr = CfgBase + GEN3_EQ_CONTROL_OFF;
  148. //
  149. // Equalization setting for Gen3
  150. //
  151. Val = MmioRead32 (Gen3RelatedAddr);
  152. Val = RATE_SHADOW_SEL_SET (Val, GEN3_DATA_RATE);
  153. MmioWrite32 (Gen3RelatedAddr, Val);
  154. Val = EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3);
  155. Val = RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ);
  156. MmioWrite32 (Gen3RelatedAddr, Val);
  157. Val = MmioRead32 (Gen3EqControlAddr);
  158. Val = GEN3_EQ_FB_MODE (Val, FOM_METHOD);
  159. Val = GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR);
  160. Val = GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM);
  161. MmioWrite32 (Gen3EqControlAddr, Val);
  162. //
  163. // Equalization setting for Gen4
  164. //
  165. Val = MmioRead32 (Gen3RelatedAddr);
  166. Val = RATE_SHADOW_SEL_SET (Val, GEN4_DATA_RATE);
  167. MmioWrite32 (Gen3RelatedAddr, Val);
  168. Val = EQ_PHASE_2_3_SET (Val, ENABLE_EQ_PHASE_2_3);
  169. Val = RXEQ_REGRDLESS_SET (Val, ASSERT_RXEQ);
  170. MmioWrite32 (Gen3RelatedAddr, Val);
  171. Val = MmioRead32 (Gen3EqControlAddr);
  172. Val = GEN3_EQ_FB_MODE (Val, FOM_METHOD);
  173. Val = GEN3_EQ_PRESET_VEC (Val, EQ_DEFAULT_PRESET_VECTOR);
  174. Val = GEN3_EQ_INIT_EVAL (Val, INCLUDE_INIT_FOM);
  175. MmioWrite32 (Gen3EqControlAddr, Val);
  176. }
  177. /**
  178. Configure presets for Gen3 equalization
  179. @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
  180. @param PcieIndex PCIe controller index
  181. **/
  182. STATIC
  183. VOID
  184. ConfigurePresetGen3 (
  185. IN AC01_ROOT_COMPLEX *RootComplex,
  186. IN UINT8 PcieIndex
  187. )
  188. {
  189. PHYSICAL_ADDRESS LaneEqControlAddr;
  190. PHYSICAL_ADDRESS SpcieCapabilityBase;
  191. UINT32 Idx;
  192. UINT32 LinkWidth;
  193. UINT32 Val;
  194. // Get the Secondary PCI Express Extended capability base address
  195. SpcieCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, SPCIE_CAPABILITY_ID);
  196. if (SpcieCapabilityBase == 0) {
  197. DEBUG ((
  198. DEBUG_ERROR,
  199. "PCIE%d.%d: Cannot get SPCIE capability address\n",
  200. RootComplex->ID,
  201. PcieIndex
  202. ));
  203. return;
  204. }
  205. LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
  206. // Each register holds the Preset for 2 lanes
  207. for (Idx = 0; Idx < (LinkWidth / 2); Idx++) {
  208. LaneEqControlAddr = SpcieCapabilityBase + SPCIE_CAP_OFF_0C_REG + Idx * sizeof (UINT32);
  209. Val = MmioRead32 (LaneEqControlAddr);
  210. Val = DSP_TX_PRESET0_SET (Val, DEFAULT_GEN3_PRESET);
  211. Val = DSP_TX_PRESET1_SET (Val, DEFAULT_GEN3_PRESET);
  212. MmioWrite32 (LaneEqControlAddr, Val);
  213. }
  214. }
  215. /**
  216. Configure presets for Gen4 equalization
  217. @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
  218. @param PcieIndex PCIe controller index
  219. **/
  220. STATIC
  221. VOID
  222. ConfigurePresetGen4 (
  223. IN AC01_ROOT_COMPLEX *RootComplex,
  224. IN UINT8 PcieIndex
  225. )
  226. {
  227. PHYSICAL_ADDRESS LaneEqControlAddr;
  228. PHYSICAL_ADDRESS Pl16gCapabilityBase;
  229. UINT32 Idx;
  230. UINT32 LinkWidth;
  231. UINT32 Val;
  232. UINT8 Preset;
  233. // Get the Physical Layer 16.0 GT/s Extended capability base address
  234. Pl16gCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, PL16G_CAPABILITY_ID);
  235. if (Pl16gCapabilityBase == 0) {
  236. DEBUG ((
  237. DEBUG_ERROR,
  238. "PCIE%d.%d: Cannot get PL16G capability address\n",
  239. RootComplex->ID,
  240. PcieIndex
  241. ));
  242. return;
  243. }
  244. if (RootComplex->PresetGen4[PcieIndex] == PRESET_INVALID) {
  245. Preset = DEFAULT_GEN4_PRESET;
  246. } else {
  247. Preset = RootComplex->PresetGen4[PcieIndex];
  248. }
  249. LinkWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
  250. if (LinkWidth == CAP_MAX_LINK_WIDTH_X2) {
  251. LaneEqControlAddr = Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG;
  252. Val = MmioRead32 (LaneEqControlAddr);
  253. Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
  254. Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
  255. MmioWrite32 (LaneEqControlAddr, Val);
  256. } else {
  257. // Each register holds the Preset for 4 lanes
  258. for (Idx = 0; Idx < (LinkWidth / 4); Idx++) {
  259. LaneEqControlAddr = Pl16gCapabilityBase + PL16G_CAP_OFF_20H_REG + Idx * sizeof (UINT32);
  260. Val = MmioRead32 (LaneEqControlAddr);
  261. Val = DSP_16G_RXTX_PRESET0_SET (Val, Preset);
  262. Val = DSP_16G_RXTX_PRESET1_SET (Val, Preset);
  263. Val = DSP_16G_RXTX_PRESET2_SET (Val, Preset);
  264. Val = DSP_16G_RXTX_PRESET3_SET (Val, Preset);
  265. MmioWrite32 (LaneEqControlAddr, Val);
  266. }
  267. }
  268. }
  269. VOID
  270. ProgramHostBridgeInfo (
  271. AC01_ROOT_COMPLEX *RootComplex
  272. )
  273. {
  274. EFI_STATUS Status;
  275. PHYSICAL_ADDRESS TargetAddress;
  276. UINT32 Val;
  277. // Program Root Complex Bifurcation
  278. if (RootComplex->Active) {
  279. if (RootComplex->Type == RootComplexTypeA) {
  280. TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCA_DEV_MAP_REG;
  281. Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
  282. if (!RETURN_ERROR (Status)) {
  283. Val = RCA_DEV_MAP_SET (Val, RootComplex->DevMapLow);
  284. MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
  285. }
  286. } else {
  287. TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_RCB_DEV_MAP_REG;
  288. Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
  289. if (!RETURN_ERROR (Status)) {
  290. Val = RCB_DEV_MAP_LOW_SET (Val, RootComplex->DevMapLow);
  291. Val = RCB_DEV_MAP_HIGH_SET (Val, RootComplex->DevMapHigh);
  292. MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
  293. }
  294. }
  295. }
  296. // Program Vendor ID and Device ID
  297. TargetAddress = RootComplex->HostBridgeBase + AC01_HOST_BRIDGE_VENDOR_DEVICE_ID_REG;
  298. Status = MailboxMsgRegisterRead (RootComplex->Socket, TargetAddress, &Val);
  299. if (!RETURN_ERROR (Status)) {
  300. Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID);
  301. if (RootComplexTypeA == RootComplex->Type) {
  302. Val = DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCA);
  303. } else {
  304. Val = DEVICE_ID_SET (Val, AC01_HOST_BRIDGE_DEVICE_ID_RCB);
  305. }
  306. MailboxMsgRegisterWrite (RootComplex->Socket, TargetAddress, Val);
  307. }
  308. }
  309. VOID
  310. ProgramRootPortInfo (
  311. AC01_ROOT_COMPLEX *RootComplex,
  312. UINT32 PcieIndex
  313. )
  314. {
  315. PHYSICAL_ADDRESS CfgBase;
  316. PHYSICAL_ADDRESS TargetAddress;
  317. UINT32 Val;
  318. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  319. // Program Class Code
  320. TargetAddress = CfgBase + TYPE1_CLASS_CODE_REV_ID_REG;
  321. Val = MmioRead32 (TargetAddress);
  322. Val = REVISION_ID_SET (Val, DEFAULT_REVISION_ID);
  323. Val = SUB_CLASS_CODE_SET (Val, DEFAULT_SUB_CLASS_CODE);
  324. Val = BASE_CLASS_CODE_SET (Val, DEFAULT_BASE_CLASS_CODE);
  325. MmioWrite32 (TargetAddress, Val);
  326. // Program Vendor ID and Device ID
  327. TargetAddress = CfgBase + TYPE1_DEV_ID_VEND_ID_REG;
  328. Val = MmioRead32 (TargetAddress);
  329. Val = VENDOR_ID_SET (Val, AMPERE_PCIE_VENDOR_ID);
  330. if (RootComplexTypeA == RootComplex->Type) {
  331. Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCA + PcieIndex);
  332. } else {
  333. Val = DEVICE_ID_SET (Val, AC01_PCIE_BRIDGE_DEVICE_ID_RCB + PcieIndex);
  334. }
  335. MmioWrite32 (TargetAddress, Val);
  336. }
  337. VOID
  338. ProgramLinkCapabilities (
  339. IN AC01_ROOT_COMPLEX *RootComplex,
  340. IN UINT8 PcieIndex
  341. )
  342. {
  343. PHYSICAL_ADDRESS CfgBase;
  344. PHYSICAL_ADDRESS TargetAddress;
  345. UINT32 Val;
  346. UINT8 MaxWidth;
  347. UINT8 MaxGen;
  348. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  349. MaxWidth = RootComplex->Pcie[PcieIndex].MaxWidth;
  350. MaxGen = RootComplex->Pcie[PcieIndex].MaxGen;
  351. TargetAddress = CfgBase + PORT_LINK_CTRL_OFF;
  352. Val = MmioRead32 (TargetAddress);
  353. switch (MaxWidth) {
  354. case LINK_WIDTH_X2:
  355. Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X2);
  356. break;
  357. case LINK_WIDTH_X4:
  358. Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X4);
  359. break;
  360. case LINK_WIDTH_X8:
  361. Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X8);
  362. break;
  363. case LINK_WIDTH_X16:
  364. default:
  365. Val = LINK_CAPABLE_SET (Val, LINK_CAPABLE_X16);
  366. break;
  367. }
  368. MmioWrite32 (TargetAddress, Val);
  369. TargetAddress = CfgBase + GEN2_CTRL_OFF;
  370. Val = MmioRead32 (TargetAddress);
  371. switch (MaxWidth) {
  372. case LINK_WIDTH_X2:
  373. Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X2);
  374. break;
  375. case LINK_WIDTH_X4:
  376. Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X4);
  377. break;
  378. case LINK_WIDTH_X8:
  379. Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X8);
  380. break;
  381. case LINK_WIDTH_X16:
  382. default:
  383. Val = NUM_OF_LANES_SET (Val, NUM_OF_LANES_X16);
  384. break;
  385. }
  386. MmioWrite32 (TargetAddress, Val);
  387. TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_REG;
  388. Val = MmioRead32 (TargetAddress);
  389. switch (MaxWidth) {
  390. case LINK_WIDTH_X2:
  391. Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X2);
  392. break;
  393. case LINK_WIDTH_X4:
  394. Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X4);
  395. break;
  396. case LINK_WIDTH_X8:
  397. Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X8);
  398. break;
  399. case LINK_WIDTH_X16:
  400. default:
  401. Val = CAP_MAX_LINK_WIDTH_SET (Val, CAP_MAX_LINK_WIDTH_X16);
  402. break;
  403. }
  404. switch (MaxGen) {
  405. case LINK_SPEED_GEN1:
  406. Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
  407. break;
  408. case LINK_SPEED_GEN2:
  409. Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
  410. break;
  411. case LINK_SPEED_GEN3:
  412. Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
  413. break;
  414. default:
  415. Val = CAP_MAX_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
  416. break;
  417. }
  418. // Enable ASPM Capability
  419. Val = CAP_ACTIVE_STATE_LINK_PM_SUPPORT_SET (Val, L0S_L1_SUPPORTED);
  420. MmioWrite32 (TargetAddress, Val);
  421. TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL2_LINK_STATUS2_REG;
  422. Val = MmioRead32 (TargetAddress);
  423. switch (MaxGen) {
  424. case LINK_SPEED_GEN1:
  425. Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_25);
  426. break;
  427. case LINK_SPEED_GEN2:
  428. Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_50);
  429. break;
  430. case LINK_SPEED_GEN3:
  431. Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_80);
  432. break;
  433. default:
  434. Val = CAP_TARGET_LINK_SPEED_SET (Val, MAX_LINK_SPEED_160);
  435. break;
  436. }
  437. MmioWrite32 (TargetAddress, Val);
  438. }
  439. VOID
  440. DisableCompletionTimeOut (
  441. IN AC01_ROOT_COMPLEX *RootComplex,
  442. IN UINT8 PcieIndex,
  443. IN BOOLEAN IsMask
  444. )
  445. {
  446. PHYSICAL_ADDRESS CfgBase;
  447. PHYSICAL_ADDRESS TargetAddress;
  448. UINT32 Val;
  449. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  450. TargetAddress = CfgBase + AER_CAPABILITY_BASE + UNCORR_ERR_MASK_OFF;
  451. Val = MmioRead32 (TargetAddress);
  452. Val = CMPLT_TIMEOUT_ERR_MASK_SET (Val, IsMask ? 1 : 0);
  453. MmioWrite32 (TargetAddress, Val);
  454. }
  455. BOOLEAN
  456. EnableItsMemory (
  457. AC01_ROOT_COMPLEX *RootComplex,
  458. UINT32 PcieIndex
  459. )
  460. {
  461. PHYSICAL_ADDRESS CsrBase;
  462. PHYSICAL_ADDRESS TargetAddress;
  463. UINT32 TimeOut;
  464. UINT32 Val;
  465. CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
  466. // Clear memory shutdown
  467. TargetAddress = CsrBase + AC01_PCIE_CORE_RAM_SHUTDOWN_REG;
  468. Val = MmioRead32 (TargetAddress);
  469. Val = SD_SET (Val, 0);
  470. MmioWrite32 (TargetAddress, Val);
  471. // Poll till ITS Memory is ready
  472. TimeOut = MEMRDY_TIMEOUT;
  473. do {
  474. Val = MmioRead32 (CsrBase + AC01_PCIE_CORE_MEM_READY_REG);
  475. if (Val & MEMORY_READY) {
  476. return TRUE;
  477. }
  478. TimeOut--;
  479. MicroSecondDelay (1);
  480. } while (TimeOut > 0);
  481. return FALSE;
  482. }
  483. BOOLEAN
  484. EnableAxiPipeClock (
  485. AC01_ROOT_COMPLEX *RootComplex,
  486. UINT32 PcieIndex
  487. )
  488. {
  489. PHYSICAL_ADDRESS CsrBase;
  490. PHYSICAL_ADDRESS TargetAddress;
  491. UINT32 TimeOut;
  492. UINT32 Val;
  493. CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
  494. // Enable subsystem clock and release reset
  495. TargetAddress = CsrBase + AC01_PCIE_CORE_CLOCK_REG;
  496. Val = MmioRead32 (TargetAddress);
  497. Val = AXIPIPE_SET (Val, 1);
  498. MmioWrite32 (TargetAddress, Val);
  499. TargetAddress = CsrBase + AC01_PCIE_CORE_RESET_REG;
  500. Val = MmioRead32 (TargetAddress);
  501. Val = DWC_PCIE_SET (Val, 0);
  502. MmioWrite32 (TargetAddress, Val);
  503. //
  504. // Controller does not provide any indicator for reset released.
  505. // Must wait at least 1us as per EAS.
  506. //
  507. MicroSecondDelay (1);
  508. // Poll till PIPE clock is stable
  509. TimeOut = PIPE_CLOCK_TIMEOUT;
  510. do {
  511. Val = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
  512. if (!(Val & PHY_STATUS_MASK)) {
  513. return TRUE;
  514. }
  515. TimeOut--;
  516. MicroSecondDelay (1);
  517. } while (TimeOut > 0);
  518. return FALSE;
  519. }
  520. VOID
  521. SetLinkTimeout (
  522. AC01_ROOT_COMPLEX *RootComplex,
  523. UINT32 PcieIndex,
  524. UINTN Timeout
  525. )
  526. {
  527. PHYSICAL_ADDRESS TargetAddress;
  528. UINT32 Val;
  529. TargetAddress = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT)
  530. + AMBA_LINK_TIMEOUT_OFF;
  531. Val = MmioRead32 (TargetAddress);
  532. Val = LINK_TIMEOUT_PERIOD_DEFAULT_SET (Val, Timeout);
  533. MmioWrite32 (TargetAddress, Val);
  534. }
  535. VOID
  536. StartLinkTraining (
  537. AC01_ROOT_COMPLEX *RootComplex,
  538. UINT32 PcieIndex,
  539. BOOLEAN StartLink
  540. )
  541. {
  542. PHYSICAL_ADDRESS TargetAddress;
  543. UINT32 Val;
  544. TargetAddress = RootComplex->Pcie[PcieIndex].CsrBase + AC01_PCIE_CORE_LINK_CTRL_REG;
  545. Val = MmioRead32 (TargetAddress);
  546. Val = LTSSMENB_SET (Val, StartLink ? START_LINK_TRAINING : HOLD_LINK_TRAINING);
  547. MmioWrite32 (TargetAddress, Val);
  548. }
  549. VOID
  550. EnableDbiAccess (
  551. AC01_ROOT_COMPLEX *RootComplex,
  552. UINT32 PcieIndex,
  553. BOOLEAN EnableDbi
  554. )
  555. {
  556. PHYSICAL_ADDRESS TargetAddress;
  557. UINT32 Val;
  558. TargetAddress = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT)
  559. + MISC_CONTROL_1_OFF;
  560. Val = MmioRead32 (TargetAddress);
  561. Val = DBI_RO_WR_EN_SET (Val, EnableDbi ? ENABLE_WR : DISABLE_WR);
  562. MmioWrite32 (TargetAddress, Val);
  563. }
  564. /**
  565. Setup and initialize the AC01 PCIe Root Complex and underneath PCIe controllers
  566. @param RootComplex Pointer to Root Complex structure
  567. @param ReInit Re-init status
  568. @param ReInitPcieIndex PCIe controller index
  569. @retval RETURN_SUCCESS The Root Complex has been initialized successfully.
  570. @retval RETURN_DEVICE_ERROR PHY, Memory or PIPE is not ready.
  571. **/
  572. RETURN_STATUS
  573. Ac01PcieCoreSetupRC (
  574. IN AC01_ROOT_COMPLEX *RootComplex,
  575. IN BOOLEAN ReInit,
  576. IN UINT8 ReInitPcieIndex
  577. )
  578. {
  579. PHYSICAL_ADDRESS CfgBase;
  580. PHYSICAL_ADDRESS CsrBase;
  581. PHYSICAL_ADDRESS TargetAddress;
  582. RETURN_STATUS Status;
  583. UINT32 Val;
  584. UINT8 PcieIndex;
  585. DEBUG ((DEBUG_INFO, "Initializing Socket%d RootComplex%d\n", RootComplex->Socket, RootComplex->ID));
  586. ProgramHostBridgeInfo (RootComplex);
  587. if (!ReInit) {
  588. Status = PciePhyInit (RootComplex->SerdesBase);
  589. if (RETURN_ERROR (Status)) {
  590. DEBUG ((DEBUG_ERROR, "%a: Failed to initialize the PCIe PHY\n", __FUNCTION__));
  591. return RETURN_DEVICE_ERROR;
  592. }
  593. }
  594. // Setup each controller
  595. for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
  596. if (ReInit) {
  597. PcieIndex = ReInitPcieIndex;
  598. }
  599. if (!RootComplex->Pcie[PcieIndex].Active) {
  600. continue;
  601. }
  602. DEBUG ((DEBUG_INFO, "Initializing Controller %d\n", PcieIndex));
  603. CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
  604. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  605. // Put Controller into reset if not in reset already
  606. TargetAddress = CsrBase + AC01_PCIE_CORE_RESET_REG;
  607. Val = MmioRead32 (TargetAddress);
  608. if (!(Val & RESET_MASK)) {
  609. Val = DWC_PCIE_SET (Val, ASSERT_RESET);
  610. MmioWrite32 (TargetAddress, Val);
  611. // Delay 50ms to ensure controller finish its reset
  612. MicroSecondDelay (50000);
  613. }
  614. if (!EnableItsMemory (RootComplex, PcieIndex)) {
  615. DEBUG ((DEBUG_ERROR, "- Pcie[%d] - ITS Memory is not ready\n", PcieIndex));
  616. return RETURN_DEVICE_ERROR;
  617. }
  618. // Hold link training
  619. StartLinkTraining (RootComplex, PcieIndex, FALSE);
  620. // Clear BUSCTRL.CfgUrMask to set CRS (Configuration Request Retry Status) to 0xFFFF.FFFF
  621. // rather than 0xFFFF.0001 as per PCIe specification requirement. Otherwise, this causes
  622. // device drivers respond incorrectly on timeout due to long device operations.
  623. TargetAddress = CsrBase + AC01_PCIE_CORE_BUS_CONTROL_REG;
  624. Val = MmioRead32 (TargetAddress);
  625. Val &= ~BUS_CTL_CFG_UR_MASK;
  626. MmioWrite32 (TargetAddress, Val);
  627. if (!EnableAxiPipeClock (RootComplex, PcieIndex)) {
  628. DEBUG ((DEBUG_ERROR, "- Pcie[%d] - PIPE clock is not stable\n", PcieIndex));
  629. return RETURN_DEVICE_ERROR;
  630. }
  631. // Start PERST pulse
  632. BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
  633. // Allow programming to config space
  634. EnableDbiAccess (RootComplex, PcieIndex, TRUE);
  635. // Program the power limit
  636. TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + SLOT_CAPABILITIES_REG;
  637. Val = MmioRead32 (TargetAddress);
  638. Val = SLOT_CAP_SLOT_POWER_LIMIT_VALUE_SET (Val, SLOT_POWER_LIMIT_75W);
  639. MmioWrite32 (TargetAddress, Val);
  640. // Program DTI for ATS support
  641. TargetAddress = CfgBase + DTIM_CTRL0_OFF;
  642. Val = MmioRead32 (TargetAddress);
  643. Val = DTIM_CTRL0_ROOT_PORT_ID_SET (Val, 0);
  644. MmioWrite32 (TargetAddress, Val);
  645. //
  646. // Program number of lanes used
  647. // - Reprogram LINK_CAPABLE of PORT_LINK_CTRL_OFF
  648. // - Reprogram NUM_OF_LANES of GEN2_CTRL_OFF
  649. // - Reprogram CAP_MAX_LINK_WIDTH of LINK_CAPABILITIES_REG
  650. //
  651. ProgramLinkCapabilities (RootComplex, PcieIndex);
  652. // Set Zero byte request handling
  653. TargetAddress = CfgBase + FILTER_MASK_2_OFF;
  654. Val = MmioRead32 (TargetAddress);
  655. Val = CX_FLT_MASK_VENMSG0_DROP_SET (Val, 0);
  656. Val = CX_FLT_MASK_VENMSG1_DROP_SET (Val, 0);
  657. Val = CX_FLT_MASK_DABORT_4UCPL_SET (Val, 0);
  658. MmioWrite32 (TargetAddress, Val);
  659. TargetAddress = CfgBase + AMBA_ORDERING_CTRL_OFF;
  660. Val = MmioRead32 (TargetAddress);
  661. Val = AX_MSTR_ZEROLREAD_FW_SET (Val, 0);
  662. MmioWrite32 (TargetAddress, Val);
  663. //
  664. // Set Completion with CRS handling for CFG Request
  665. // Set Completion with CA/UR handling non-CFG Request
  666. //
  667. TargetAddress = CfgBase + AMBA_ERROR_RESPONSE_DEFAULT_OFF;
  668. Val = MmioRead32 (TargetAddress);
  669. // 0x2: OKAY with FFFF_0001 and FFFF_FFFF
  670. Val = AMBA_ERROR_RESPONSE_CRS_SET (Val, 0x2);
  671. MmioWrite32 (TargetAddress, Val);
  672. // Set Legacy PCIE interrupt map to INTA
  673. TargetAddress = CfgBase + BRIDGE_CTRL_INT_PIN_INT_LINE_REG;
  674. Val = MmioRead32 (TargetAddress);
  675. Val = INT_PIN_SET (Val, IRQ_INT_A);
  676. MmioWrite32 (TargetAddress, Val);
  677. TargetAddress = CsrBase + AC01_PCIE_CORE_IRQ_SEL_REG;
  678. Val = MmioRead32 (TargetAddress);
  679. Val = INTPIN_SET (Val, IRQ_INT_A);
  680. MmioWrite32 (TargetAddress, Val);
  681. if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN2) {
  682. ConfigureEqualization (RootComplex, PcieIndex);
  683. if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN3) {
  684. ConfigurePresetGen3 (RootComplex, PcieIndex);
  685. if (RootComplex->Pcie[PcieIndex].MaxGen >= LINK_SPEED_GEN4) {
  686. ConfigurePresetGen4 (RootComplex, PcieIndex);
  687. }
  688. }
  689. }
  690. // Link timeout after 1ms
  691. SetLinkTimeout (RootComplex, PcieIndex, 1);
  692. DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE);
  693. ProgramRootPortInfo (RootComplex, PcieIndex);
  694. // Enable common clock for downstream
  695. TargetAddress = CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG;
  696. Val = MmioRead32 (TargetAddress);
  697. Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
  698. Val = CAP_COMMON_CLK_SET (Val, 1);
  699. MmioWrite32 (TargetAddress, Val);
  700. // Match aux_clk to system
  701. TargetAddress = CfgBase + AUX_CLK_FREQ_OFF;
  702. Val = MmioRead32 (TargetAddress);
  703. Val = AUX_CLK_FREQ_SET (Val, AUX_CLK_500MHZ);
  704. MmioWrite32 (TargetAddress, Val);
  705. // Assert PERST low to reset endpoint
  706. BoardPcieAssertPerst (RootComplex, PcieIndex, FALSE);
  707. // Start link training
  708. StartLinkTraining (RootComplex, PcieIndex, TRUE);
  709. // Complete the PERST pulse
  710. BoardPcieAssertPerst (RootComplex, PcieIndex, TRUE);
  711. // Lock programming of config space
  712. EnableDbiAccess (RootComplex, PcieIndex, FALSE);
  713. if (ReInit) {
  714. return RETURN_SUCCESS;
  715. }
  716. }
  717. return RETURN_SUCCESS;
  718. }
  719. BOOLEAN
  720. PcieLinkUpCheck (
  721. IN AC01_PCIE_CONTROLLER *Pcie
  722. )
  723. {
  724. PHYSICAL_ADDRESS CsrBase;
  725. UINT32 BlockEvent;
  726. UINT32 LinkStat;
  727. CsrBase = Pcie->CsrBase;
  728. // Check if card present
  729. // smlh_ltssm_state[13:8] = 0
  730. // phy_status[2] = 0
  731. // smlh_link_up[1] = 0
  732. // rdlh_link_up[0] = 0
  733. LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
  734. LinkStat = LinkStat & (SMLH_LTSSM_STATE_MASK | PHY_STATUS_MASK_BIT |
  735. SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT);
  736. if (LinkStat == 0) {
  737. return FALSE;
  738. }
  739. BlockEvent = MmioRead32 (CsrBase + AC01_PCIE_CORE_BLOCK_EVENT_STAT_REG);
  740. LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
  741. if (((BlockEvent & LINKUP_MASK) != 0)
  742. && (SMLH_LTSSM_STATE_GET(LinkStat) == LTSSM_STATE_L0)) {
  743. return TRUE;
  744. }
  745. return FALSE;
  746. }
  747. /**
  748. Callback function when the Host Bridge enumeration end.
  749. @param RootComplex Pointer to the Root Complex structure
  750. **/
  751. VOID
  752. Ac01PcieCoreEndEnumeration (
  753. IN AC01_ROOT_COMPLEX *RootComplex
  754. )
  755. {
  756. PHYSICAL_ADDRESS TargetAddress;
  757. UINT32 PcieIndex;
  758. UINT32 Val;
  759. if (RootComplex == NULL || !RootComplex->Active) {
  760. return;
  761. }
  762. // Clear uncorrectable error during enumuration phase. Mainly completion timeout.
  763. for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
  764. if (!RootComplex->Pcie[PcieIndex].Active) {
  765. continue;
  766. }
  767. if (!PcieLinkUpCheck(&RootComplex->Pcie[PcieIndex])) {
  768. // If link down/disabled after enumeration, disable completed time out
  769. DisableCompletionTimeOut (RootComplex, PcieIndex, TRUE);
  770. }
  771. // Clear all errors
  772. TargetAddress = RootComplex->MmcfgBase + ((PcieIndex + 1) << DEV_SHIFT) \
  773. + AER_CAPABILITY_BASE + UNCORR_ERR_STATUS_OFF;
  774. Val = MmioRead32 (TargetAddress);
  775. if (Val != 0) {
  776. // Clear error by writting
  777. MmioWrite32 (TargetAddress, Val);
  778. }
  779. }
  780. }
  781. /**
  782. Comparing current link status with the max capabilities of the link
  783. @param RootComplex Pointer to AC01_ROOT_COMPLEX structure
  784. @param PcieIndex PCIe controller index
  785. @param EpMaxWidth EP max link width
  786. @param EpMaxGen EP max link speed
  787. @retval -1: Link status do not match with link max capabilities
  788. 1: Link capabilites are invalid
  789. 0: Link status are correct
  790. **/
  791. INT32
  792. Ac01PcieCoreLinkCheck (
  793. IN AC01_ROOT_COMPLEX *RootComplex,
  794. IN UINT8 PcieIndex,
  795. IN UINT8 EpMaxWidth,
  796. IN UINT8 EpMaxGen
  797. )
  798. {
  799. PHYSICAL_ADDRESS CsrBase, CfgBase;
  800. UINT32 Val, LinkStat;
  801. UINT32 MaxWidth, MaxGen;
  802. CsrBase = RootComplex->Pcie[PcieIndex].CsrBase;
  803. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  804. Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CAPABILITIES_REG);
  805. if ((CAP_MAX_LINK_WIDTH_GET (Val) == 0) ||
  806. (CAP_MAX_LINK_SPEED_GET (Val) == 0)) {
  807. DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong RootComplex capabilities\n", RootComplex->ID, PcieIndex));
  808. return LINK_CHECK_WRONG_PARAMETER;
  809. }
  810. if ((EpMaxWidth == 0) || (EpMaxGen == 0)) {
  811. DEBUG ((DEBUG_INFO, "\tPCIE%d.%d: Wrong EP capabilities\n", RootComplex->ID, PcieIndex));
  812. return LINK_CHECK_FAILED;
  813. }
  814. // Compare RootComplex and EP capabilities
  815. if (CAP_MAX_LINK_WIDTH_GET (Val) > EpMaxWidth) {
  816. MaxWidth = EpMaxWidth;
  817. } else {
  818. MaxWidth = CAP_MAX_LINK_WIDTH_GET (Val);
  819. }
  820. // Compare RootComplex and EP capabilities
  821. if (CAP_MAX_LINK_SPEED_GET (Val) > EpMaxGen) {
  822. MaxGen = EpMaxGen;
  823. } else {
  824. MaxGen = CAP_MAX_LINK_SPEED_GET (Val);
  825. }
  826. LinkStat = MmioRead32 (CsrBase + AC01_PCIE_CORE_LINK_STAT_REG);
  827. Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG);
  828. DEBUG ((
  829. DEBUG_INFO,
  830. "PCIE%d.%d: Link MaxWidth %d MaxGen %d, AC01_PCIE_CORE_LINK_STAT_REG 0x%x",
  831. RootComplex->ID,
  832. PcieIndex,
  833. MaxWidth,
  834. MaxGen,
  835. LinkStat
  836. ));
  837. // Checking all conditions of the link
  838. // If one of them is not sastified, return link up fail
  839. if ((CAP_NEGO_LINK_WIDTH_GET (Val) != MaxWidth) ||
  840. (CAP_LINK_SPEED_GET (Val) != MaxGen) ||
  841. (RDLH_SMLH_LINKUP_STATUS_GET (LinkStat) != (SMLH_LINK_UP_MASK_BIT | RDLH_LINK_UP_MASK_BIT)))
  842. {
  843. DEBUG ((DEBUG_INFO, "\tLinkCheck FAILED\n"));
  844. return LINK_CHECK_FAILED;
  845. }
  846. DEBUG ((DEBUG_INFO, "\tLinkCheck SUCCESS\n"));
  847. return LINK_CHECK_SUCCESS;
  848. }
  849. INT32
  850. PFACounterRead (
  851. IN AC01_ROOT_COMPLEX *RootComplex,
  852. IN UINT8 PcieIndex,
  853. IN UINT64 RasDesCapabilityBase
  854. )
  855. {
  856. INT32 Ret = LINK_CHECK_SUCCESS;
  857. UINT32 Val;
  858. UINT8 ErrCode, ErrGrpNum;
  859. UINT32 ErrCtrlCfg[] = {
  860. 0x000, 0x001, 0x002, 0x003, 0x004, 0x005, 0x006, 0x007, 0x008, 0x009, 0x00A, // Per Lane
  861. 0x105, 0x106, 0x107, 0x108, 0x109, 0x10A,
  862. 0x200, 0x201, 0x202, 0x203, 0x204, 0x205, 0x206, 0x207,
  863. 0x300, 0x301, 0x302, 0x303, 0x304, 0x305,
  864. 0x400, 0x401, // Per Lane
  865. 0x500, 0x501, 0x502, 0x503, 0x504, 0x505, 0x506, 0x507, 0x508, 0x509, 0x50A, 0x50B, 0x50C, 0x50D
  866. };
  867. for (ErrCode = 0; ErrCode < ARRAY_SIZE (ErrCtrlCfg); ErrCode++) {
  868. ErrGrpNum = GET_HIGH_8_BITS (ErrCtrlCfg[ErrCode]);
  869. // Skipping per lane group
  870. // Checking common lane group because AER error are included in common group only
  871. if ((ErrGrpNum != 0) && (ErrGrpNum != 4)) {
  872. Val = MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG);
  873. if (RootComplex->Type == RootComplexTypeA) {
  874. // RootComplexTypeA - 4 PCIe controller per port, 1 controller in charge of 4 lanes
  875. Val = ECCR_LANE_SEL_SET (Val, PcieIndex * 4);
  876. } else {
  877. // RootComplexTypeB - 8 PCIe controller per port, 1 controller in charge of 2 lanes
  878. Val = ECCR_LANE_SEL_SET (Val, PcieIndex * 2);
  879. }
  880. Val = ECCR_GROUP_EVENT_SEL_SET (Val, ErrCtrlCfg[ErrCode]);
  881. MmioWrite32 (RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG, Val);
  882. // After setting Counter Control reg
  883. // This delay just to make sure Counter Data reg is update with new value
  884. MicroSecondDelay (1);
  885. Val = MmioRead32 (RasDesCapabilityBase + EVENT_COUNTER_DATA_REG);
  886. if (Val != 0) {
  887. Ret = LINK_CHECK_FAILED;
  888. DEBUG ((
  889. DEBUG_ERROR,
  890. "\tSocket%d RootComplex%d RP%d \t%s: %d \tGROUP:%d-EVENT:%d\n",
  891. RootComplex->Socket,
  892. RootComplex->ID,
  893. PcieIndex,
  894. Val,
  895. ErrGrpNum,
  896. GET_LOW_8_BITS (ErrCtrlCfg[ErrCode])
  897. ));
  898. }
  899. }
  900. }
  901. return Ret;
  902. }
  903. /**
  904. Handle Predictive Failure Analysis command
  905. @param RootComplex Pointer to Root Complex structure
  906. @param PcieIndex PCIe controller index
  907. @param PFAMode The PFA mode
  908. @retval The link status
  909. **/
  910. INT32
  911. Ac01PFACommand (
  912. IN AC01_ROOT_COMPLEX *RootComplex,
  913. IN UINT8 PcieIndex,
  914. IN UINT8 PFAMode
  915. )
  916. {
  917. PHYSICAL_ADDRESS RasDesCapabilityBase;
  918. PHYSICAL_ADDRESS TargetAddress;
  919. INT32 Ret = LINK_CHECK_SUCCESS;
  920. UINT32 Val;
  921. // Allow programming to config space
  922. EnableDbiAccess (RootComplex, PcieIndex, TRUE);
  923. // Get the RAS D.E.S. capability base address
  924. RasDesCapabilityBase = GetCapabilityBase (RootComplex, PcieIndex, TRUE, RAS_DES_CAPABILITY_ID);
  925. if (RasDesCapabilityBase == 0) {
  926. DEBUG ((DEBUG_INFO, "PCIE%d.%d: Cannot get RAS DES capability address\n", RootComplex->ID, PcieIndex));
  927. return LINK_CHECK_WRONG_PARAMETER;
  928. }
  929. TargetAddress = RasDesCapabilityBase + EVENT_COUNTER_CONTROL_REG;
  930. switch (PFAMode) {
  931. case PFA_MODE_ENABLE:
  932. Val = MmioRead32 (TargetAddress);
  933. Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_ALL_ON);
  934. Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_NO_CHANGE);
  935. MmioWrite32 (TargetAddress, Val);
  936. break;
  937. case PFA_MODE_CLEAR:
  938. Val = MmioRead32 (TargetAddress);
  939. Val = ECCR_EVENT_COUNTER_ENABLE_SET (Val, EVENT_COUNTER_ENABLE_NO_CHANGE);
  940. Val = ECCR_EVENT_COUNTER_CLEAR_SET (Val, EVENT_COUNTER_CLEAR_ALL_CLEAR);
  941. MmioWrite32 (TargetAddress, Val);
  942. break;
  943. case PFA_MODE_READ:
  944. Ret = PFACounterRead (RootComplex, PcieIndex, RasDesCapabilityBase);
  945. break;
  946. default:
  947. DEBUG ((DEBUG_ERROR, "%a: Invalid PFA mode\n"));
  948. }
  949. // Disable programming to config space
  950. EnableDbiAccess (RootComplex, PcieIndex, FALSE);
  951. return Ret;
  952. }
  953. BOOLEAN
  954. EndpointCfgReady (
  955. IN AC01_ROOT_COMPLEX *RootComplex,
  956. IN UINT8 PcieIndex,
  957. IN UINT32 TimeOut
  958. )
  959. {
  960. PHYSICAL_ADDRESS CfgBase;
  961. UINT32 Val;
  962. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
  963. // Loop read CfgBase value until got valid value or
  964. // reach to Timeout (or more depend on card)
  965. do {
  966. Val = MmioRead32 (CfgBase);
  967. if (Val != 0xFFFF0001 && Val != 0xFFFFFFFF) {
  968. return TRUE;
  969. }
  970. TimeOut -= LINK_WAIT_INTERVAL_US;
  971. MicroSecondDelay (LINK_WAIT_INTERVAL_US);
  972. } while (TimeOut > 0);
  973. return FALSE;
  974. }
  975. /**
  976. Get link capabilities link width and speed of endpoint
  977. @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure
  978. @param PcieIndex[in] PCIe controller index
  979. @param EpMaxWidth[out] EP max link width
  980. @param EpMaxGen[out] EP max link speed
  981. **/
  982. VOID
  983. Ac01PcieCoreGetEndpointInfo (
  984. IN AC01_ROOT_COMPLEX *RootComplex,
  985. IN UINT8 PcieIndex,
  986. OUT UINT8 *EpMaxWidth,
  987. OUT UINT8 *EpMaxGen
  988. )
  989. {
  990. PHYSICAL_ADDRESS CfgBase;
  991. PHYSICAL_ADDRESS EpCfgAddr;
  992. PHYSICAL_ADDRESS PcieCapBase;
  993. PHYSICAL_ADDRESS SecLatTimerAddr;
  994. PHYSICAL_ADDRESS TargetAddress;
  995. UINT32 RestoreVal;
  996. UINT32 Val;
  997. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  998. SecLatTimerAddr = CfgBase + SEC_LAT_TIMER_SUB_BUS_SEC_BUS_PRI_BUS_REG;
  999. *EpMaxWidth = 0;
  1000. *EpMaxGen = 0;
  1001. // Allow programming to config space
  1002. EnableDbiAccess (RootComplex, PcieIndex, TRUE);
  1003. Val = MmioRead32 (SecLatTimerAddr);
  1004. RestoreVal = Val;
  1005. Val = SUB_BUS_SET (Val, DEFAULT_SUB_BUS);
  1006. Val = SEC_BUS_SET (Val, RootComplex->Pcie[PcieIndex].DevNum);
  1007. Val = PRIM_BUS_SET (Val, DEFAULT_PRIM_BUS);
  1008. MmioWrite32 (SecLatTimerAddr, Val);
  1009. EpCfgAddr = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << BUS_SHIFT);
  1010. if (!EndpointCfgReady (RootComplex, PcieIndex, EP_LINKUP_EXTRA_TIMEOUT)) {
  1011. goto Exit;
  1012. }
  1013. Val = MmioRead32 (EpCfgAddr);
  1014. // Check whether EP config space is accessible or not
  1015. if (Val == 0xFFFFFFFF) {
  1016. *EpMaxWidth = 0; // Invalid Width
  1017. *EpMaxGen = 0; // Invalid Speed
  1018. DEBUG ((DEBUG_ERROR, "PCIE%d.%d Cannot access EP config space!\n", RootComplex->ID, PcieIndex));
  1019. } else if (Val == 0xFFFF0001) {
  1020. *EpMaxWidth = 0; // Invalid Width
  1021. *EpMaxGen = 0; // Invalid Speed
  1022. DEBUG ((DEBUG_ERROR, "PCIE%d.%d EP config space still not ready to access, need poll more time!!!\n", RootComplex->ID, PcieIndex));
  1023. } else {
  1024. PcieCapBase = GetCapabilityBase (RootComplex, PcieIndex, FALSE, PCIE_CAPABILITY_ID);
  1025. if (PcieCapBase == 0) {
  1026. DEBUG ((
  1027. DEBUG_ERROR,
  1028. "PCIE%d.%d Cannot get PCIe capability base address!\n",
  1029. RootComplex->ID,
  1030. PcieIndex
  1031. ));
  1032. } else {
  1033. Val = MmioRead32 (PcieCapBase + LINK_CAPABILITIES_REG);
  1034. *EpMaxWidth = CAP_MAX_LINK_WIDTH_GET (Val);
  1035. *EpMaxGen = CAP_MAX_LINK_SPEED_GET (Val);
  1036. DEBUG ((
  1037. DEBUG_INFO,
  1038. "PCIE%d.%d EP MaxWidth %d EP MaxGen %d \n", RootComplex->ID,
  1039. PcieIndex,
  1040. *EpMaxWidth,
  1041. *EpMaxGen
  1042. ));
  1043. // From EP, enabling common clock for upstream
  1044. TargetAddress = PcieCapBase + LINK_CONTROL_LINK_STATUS_REG;
  1045. Val = MmioRead32 (TargetAddress);
  1046. Val = CAP_SLOT_CLK_CONFIG_SET (Val, 1);
  1047. Val = CAP_COMMON_CLK_SET (Val, 1);
  1048. MmioWrite32 (TargetAddress, Val);
  1049. }
  1050. }
  1051. Exit:
  1052. // Restore value in order to not affect enumeration process
  1053. MmioWrite32 (SecLatTimerAddr, RestoreVal);
  1054. // Disable programming to config space
  1055. EnableDbiAccess (RootComplex, PcieIndex, FALSE);
  1056. }
  1057. VOID
  1058. PollLinkUp (
  1059. IN AC01_ROOT_COMPLEX *RootComplex,
  1060. IN UINT8 PcieIndex
  1061. )
  1062. {
  1063. UINT32 TimeOut;
  1064. // Poll until link up
  1065. // This checking for linkup status and
  1066. // give LTSSM state the time to transit from DECTECT state to L0 state
  1067. // Total delay are 100ms, smaller number of delay cannot always make sure
  1068. // the state transition is completed
  1069. TimeOut = LTSSM_TRANSITION_TIMEOUT;
  1070. do {
  1071. if (PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex])) {
  1072. DEBUG ((
  1073. DEBUG_INFO,
  1074. "\tPCIE%d.%d LinkStat is correct after soft reset, transition time: %d\n",
  1075. RootComplex->ID,
  1076. PcieIndex,
  1077. TimeOut
  1078. ));
  1079. RootComplex->Pcie[PcieIndex].LinkUp = TRUE;
  1080. break;
  1081. }
  1082. MicroSecondDelay (100);
  1083. TimeOut -= 100;
  1084. } while (TimeOut > 0);
  1085. if (TimeOut <= 0) {
  1086. DEBUG ((DEBUG_ERROR, "\tPCIE%d.%d LinkStat TIMEOUT after re-init\n", RootComplex->ID, PcieIndex));
  1087. } else {
  1088. DEBUG ((DEBUG_INFO, "PCIE%d.%d Link re-initialization passed!\n", RootComplex->ID, PcieIndex));
  1089. }
  1090. }
  1091. /**
  1092. Check active PCIe controllers of RootComplex, retrain or soft reset if needed
  1093. @param RootComplex[in] Pointer to AC01_ROOT_COMPLEX structure
  1094. @param PcieIndex[in] PCIe controller index
  1095. @retval -1: Link recovery had failed
  1096. 1: Link width and speed are not correct
  1097. 0: Link recovery succeed
  1098. **/
  1099. INT32
  1100. Ac01PcieCoreQoSLinkCheckRecovery (
  1101. IN AC01_ROOT_COMPLEX *RootComplex,
  1102. IN UINT8 PcieIndex
  1103. )
  1104. {
  1105. INT32 LinkStatusCheck, RasdesChecking;
  1106. INT32 NumberOfReset = MAX_REINIT;
  1107. UINT8 EpMaxWidth, EpMaxGen;
  1108. // PCIe controller is not active or Link is not up
  1109. // Nothing to be done
  1110. if ((!RootComplex->Pcie[PcieIndex].Active) || (!RootComplex->Pcie[PcieIndex].LinkUp)) {
  1111. return LINK_CHECK_WRONG_PARAMETER;
  1112. }
  1113. do {
  1114. if (RootComplex->Pcie[PcieIndex].LinkUp) {
  1115. // Enable all of RASDES register to detect any training error
  1116. Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_ENABLE);
  1117. // Accessing Endpoint and checking current link capabilities
  1118. Ac01PcieCoreGetEndpointInfo (RootComplex, PcieIndex, &EpMaxWidth, &EpMaxGen);
  1119. LinkStatusCheck = Ac01PcieCoreLinkCheck (RootComplex, PcieIndex, EpMaxWidth, EpMaxGen);
  1120. // Delay to allow the link to perform internal operation and generate
  1121. // any error status update. This allows detection of any error observed
  1122. // during initial link training. Possible evaluation time can be
  1123. // between 100ms to 200ms.
  1124. MicroSecondDelay (100000);
  1125. // Check for error
  1126. RasdesChecking = Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_READ);
  1127. // Clear error counter
  1128. Ac01PFACommand (RootComplex, PcieIndex, PFA_MODE_CLEAR);
  1129. // If link check functions return passed, then breaking out
  1130. // else go to soft reset
  1131. if (LinkStatusCheck != LINK_CHECK_FAILED &&
  1132. RasdesChecking != LINK_CHECK_FAILED &&
  1133. PcieLinkUpCheck (&RootComplex->Pcie[PcieIndex]))
  1134. {
  1135. return LINK_CHECK_SUCCESS;
  1136. }
  1137. RootComplex->Pcie[PcieIndex].LinkUp = FALSE;
  1138. }
  1139. // Trigger controller soft reset
  1140. DEBUG ((DEBUG_INFO, "PCIE%d.%d Start link re-initialization..\n", RootComplex->ID, PcieIndex));
  1141. Ac01PcieCoreSetupRC (RootComplex, TRUE, PcieIndex);
  1142. PollLinkUp (RootComplex, PcieIndex);
  1143. NumberOfReset--;
  1144. } while (NumberOfReset > 0);
  1145. return LINK_CHECK_SUCCESS;
  1146. }
  1147. BOOLEAN
  1148. Ac01PcieCoreCheckCardPresent (
  1149. IN AC01_PCIE_CONTROLLER *PcieController
  1150. )
  1151. {
  1152. EFI_PHYSICAL_ADDRESS TargetAddress;
  1153. UINT32 ControlValue;
  1154. ControlValue = 0;
  1155. TargetAddress = PcieController->CsrBase;
  1156. ControlValue = MmioRead32 (TargetAddress + AC01_PCIE_CORE_LINK_CTRL_REG);
  1157. if (0 == LTSSMENB_GET (ControlValue)) {
  1158. //
  1159. // LTSSMENB is clear to 0x00 by Hardware -> link partner is connected.
  1160. //
  1161. return TRUE;
  1162. }
  1163. return FALSE;
  1164. }
  1165. VOID
  1166. Ac01PcieCoreUpdateLink (
  1167. IN AC01_ROOT_COMPLEX *RootComplex,
  1168. OUT BOOLEAN *IsNextRoundNeeded,
  1169. OUT INT8 *FailedPciePtr,
  1170. OUT INT8 *FailedPcieCount
  1171. )
  1172. {
  1173. AC01_PCIE_CONTROLLER *Pcie;
  1174. PHYSICAL_ADDRESS CfgBase;
  1175. UINT8 PcieIndex;
  1176. UINT32 Index;
  1177. UINT32 Val;
  1178. *IsNextRoundNeeded = FALSE;
  1179. *FailedPcieCount = 0;
  1180. for (Index = 0; Index < MaxPcieControllerOfRootComplexB; Index++) {
  1181. FailedPciePtr[Index] = -1;
  1182. }
  1183. if (!RootComplex->Active) {
  1184. return;
  1185. }
  1186. // Loop for all controllers
  1187. for (PcieIndex = 0; PcieIndex < RootComplex->MaxPcieController; PcieIndex++) {
  1188. Pcie = &RootComplex->Pcie[PcieIndex];
  1189. CfgBase = RootComplex->MmcfgBase + (RootComplex->Pcie[PcieIndex].DevNum << DEV_SHIFT);
  1190. if (Pcie->Active && !Pcie->LinkUp) {
  1191. if (PcieLinkUpCheck (Pcie)) {
  1192. Pcie->LinkUp = TRUE;
  1193. Val = MmioRead32 (CfgBase + PCIE_CAPABILITY_BASE + LINK_CONTROL_LINK_STATUS_REG);
  1194. // Doing link checking and recovery if needed
  1195. Ac01PcieCoreQoSLinkCheckRecovery (RootComplex, PcieIndex);
  1196. // Un-mask Completion Timeout
  1197. DisableCompletionTimeOut (RootComplex, PcieIndex, FALSE);
  1198. } else {
  1199. FailedPciePtr[*FailedPcieCount] = PcieIndex;
  1200. *FailedPcieCount += 1;
  1201. *IsNextRoundNeeded = !(*IsNextRoundNeeded) ? Ac01PcieCoreCheckCardPresent (Pcie) : TRUE;
  1202. }
  1203. }
  1204. }
  1205. }
  1206. /**
  1207. Verify the link status and retry to initialize the Root Complex if there's any issue.
  1208. @param RootComplexList Pointer to the Root Complex list
  1209. **/
  1210. VOID
  1211. Ac01PcieCorePostSetupRC (
  1212. IN AC01_ROOT_COMPLEX *RootComplexList
  1213. )
  1214. {
  1215. UINT8 RCIndex, Idx;
  1216. BOOLEAN IsNextRoundNeeded, NextRoundNeeded;
  1217. UINT64 PrevTick, CurrTick, ElapsedCycle;
  1218. UINT64 TimerTicks64;
  1219. UINT8 ReInit;
  1220. INT8 FailedPciePtr[MaxPcieControllerOfRootComplexB];
  1221. INT8 FailedPcieCount;
  1222. ReInit = 0;
  1223. _link_polling:
  1224. NextRoundNeeded = FALSE;
  1225. //
  1226. // It is not guaranteed the timer service is ready prior to PCI Dxe.
  1227. // Calculate system ticks for link training.
  1228. //
  1229. TimerTicks64 = ArmGenericTimerGetTimerFreq (); /* 1 Second */
  1230. PrevTick = ArmGenericTimerGetSystemCount ();
  1231. ElapsedCycle = 0;
  1232. do {
  1233. CurrTick = ArmGenericTimerGetSystemCount ();
  1234. if (CurrTick < PrevTick) {
  1235. ElapsedCycle += MAX_UINT64 - PrevTick;
  1236. PrevTick = 0;
  1237. }
  1238. ElapsedCycle += (CurrTick - PrevTick);
  1239. PrevTick = CurrTick;
  1240. } while (ElapsedCycle < TimerTicks64);
  1241. for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
  1242. Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount);
  1243. if (IsNextRoundNeeded) {
  1244. NextRoundNeeded = TRUE;
  1245. }
  1246. }
  1247. if (NextRoundNeeded && ReInit < MAX_REINIT) {
  1248. //
  1249. // Timer is up. Give another chance to re-program controller
  1250. //
  1251. ReInit++;
  1252. for (RCIndex = 0; RCIndex < AC01_PCIE_MAX_ROOT_COMPLEX; RCIndex++) {
  1253. Ac01PcieCoreUpdateLink (&RootComplexList[RCIndex], &IsNextRoundNeeded, FailedPciePtr, &FailedPcieCount);
  1254. if (IsNextRoundNeeded) {
  1255. for (Idx = 0; Idx < FailedPcieCount; Idx++) {
  1256. if (FailedPciePtr[Idx] == -1) {
  1257. continue;
  1258. }
  1259. //
  1260. // Some controller still observes link-down. Re-init controller
  1261. //
  1262. Ac01PcieCoreSetupRC (&RootComplexList[RCIndex], TRUE, FailedPciePtr[Idx]);
  1263. }
  1264. }
  1265. }
  1266. goto _link_polling;
  1267. }
  1268. }