BoardPcieLib.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. /** @file
  2. Pcie board specific driver to handle asserting PERST signal to Endpoint
  3. card. PERST asserting is via group of GPIO pins to CPLD as Platform Specification.
  4. Copyright (c) 2020 - 2023, Ampere Computing LLC. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <PiDxe.h>
  8. #include <Guid/RootComplexInfoHob.h>
  9. #include <Library/DebugLib.h>
  10. #include <Library/GpioLib.h>
  11. #include <Library/TimerLib.h>
  12. #include <Platform/Ac01.h>
  13. #define RCA_MAX_PERST_GROUPVAL 62
  14. #define RCB_MAX_PERST_GROUPVAL 46
  15. #define DEFAULT_SEGMENT_NUMBER 0x0F
  16. #define PCIE_PERST_DELAY (100 * 1000) // 100ms
  17. VOID
  18. BoardPcieReleaseAllPerst (
  19. IN UINT8 SocketId
  20. )
  21. {
  22. UINT32 GpioIndex, GpioPin;
  23. // Write 1 to all GPIO[16..21] to release all PERST
  24. GpioPin = AC01_GPIO_PINS_PER_SOCKET * SocketId + 16;
  25. for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
  26. GpioModeConfig (GpioPin + GpioIndex, GpioConfigOutHigh);
  27. }
  28. MicroSecondDelay (PCIE_PERST_DELAY);
  29. }
  30. EFI_STATUS
  31. GetGpioGroup (
  32. IN UINT8 RootComplexId,
  33. IN UINT8 PcieIndex,
  34. OUT UINT32 *GpioGroupVal
  35. )
  36. {
  37. /* Ampere Altra Max RootComplex->ID: 4:7 */
  38. if (PcieIndex < 2) {
  39. switch (RootComplexId) {
  40. case 4:
  41. *GpioGroupVal = 34 - (PcieIndex * 2);
  42. break;
  43. case 5:
  44. *GpioGroupVal = 38 - (PcieIndex * 2);
  45. break;
  46. case 6:
  47. *GpioGroupVal = 30 - (PcieIndex * 2);
  48. break;
  49. case 7:
  50. *GpioGroupVal = 26 - (PcieIndex * 2);
  51. break;
  52. default:
  53. return EFI_INVALID_PARAMETER;
  54. }
  55. } else {
  56. /* Ampere Altra Max RootComplex->ID: 4:7 */
  57. switch (RootComplexId) {
  58. case 4:
  59. *GpioGroupVal = 46 - ((PcieIndex - 2) * 2);
  60. break;
  61. case 5:
  62. *GpioGroupVal = 42 - ((PcieIndex - 2) * 2);
  63. break;
  64. case 6:
  65. *GpioGroupVal = 18 - ((PcieIndex - 2) * 2);
  66. break;
  67. case 7:
  68. *GpioGroupVal = 22 - ((PcieIndex - 2) * 2);
  69. break;
  70. default:
  71. return EFI_INVALID_PARAMETER;
  72. }
  73. }
  74. return EFI_SUCCESS;
  75. }
  76. /**
  77. Assert PERST of PCIe controller
  78. @param[in] RootComplex Root Complex instance.
  79. @param[in] PcieIndex PCIe controller index of input Root Complex.
  80. @param[in] IsPullToHigh Target status for the PERST.
  81. @retval RETURN_SUCCESS The operation is successful.
  82. @retval Others An error occurred.
  83. **/
  84. RETURN_STATUS
  85. EFIAPI
  86. BoardPcieAssertPerst (
  87. IN AC01_ROOT_COMPLEX *RootComplex,
  88. IN UINT8 PcieIndex,
  89. IN BOOLEAN IsPullToHigh
  90. )
  91. {
  92. UINT32 GpioGroupVal;
  93. UINT32 Val;
  94. UINT32 GpioIndex;
  95. UINT32 GpioPin;
  96. EFI_STATUS Status;
  97. if (!IsPullToHigh) {
  98. if (RootComplex->Type == RootComplexTypeA) {
  99. if (RootComplex->ID < MaxPcieControllerOfRootComplexA) {
  100. /* Ampere Altra: 4 */
  101. //
  102. // RootComplexTypeA: RootComplex->ID: 0->3 ; PcieIndex: 0->3
  103. //
  104. GpioGroupVal = RCA_MAX_PERST_GROUPVAL - PcieIndex
  105. - RootComplex->ID * MaxPcieControllerOfRootComplexA;
  106. } else {
  107. Status = GetGpioGroup (RootComplex->ID, PcieIndex, &GpioGroupVal);
  108. if (EFI_ERROR (Status)) {
  109. DEBUG ((DEBUG_ERROR, "Invalid Root Complex ID %d\n", RootComplex->ID));
  110. return Status;
  111. }
  112. }
  113. } else {
  114. //
  115. // RootComplexTypeB: RootComplex->ID: 4->7 ; PcieIndex: 0->7
  116. //
  117. GpioGroupVal = RCB_MAX_PERST_GROUPVAL - PcieIndex
  118. - (RootComplex->ID - MaxRootComplexA) * MaxPcieControllerOfRootComplexB;
  119. }
  120. // Update the value of GPIO[16..21]. Corresponding PERST line will be decoded by CPLD.
  121. GpioPin = AC01_GPIO_PINS_PER_SOCKET * RootComplex->Socket + 16;
  122. for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
  123. Val = (GpioGroupVal & 0x3F) & (1 << GpioIndex);
  124. if (Val == 0) {
  125. GpioModeConfig (GpioPin + GpioIndex, GpioConfigOutLow);
  126. } else {
  127. GpioModeConfig (GpioPin + GpioIndex, GpioConfigOutHigh);
  128. }
  129. }
  130. // Keep reset as low as 100 ms as specification
  131. MicroSecondDelay (PCIE_PERST_DELAY);
  132. } else {
  133. BoardPcieReleaseAllPerst (RootComplex->Socket);
  134. }
  135. return RETURN_SUCCESS;
  136. }
  137. /**
  138. Override the segment number for a root complex with a board specific number.
  139. @param[in] RootComplex Root Complex instance with properties.
  140. @retval Segment number corresponding to the input root complex.
  141. Default segment number is 0x0F.
  142. **/
  143. UINT16
  144. BoardPcieGetSegmentNumber (
  145. IN AC01_ROOT_COMPLEX *RootComplex
  146. )
  147. {
  148. UINT8 Ac01BoardSegment[PLATFORM_CPU_MAX_SOCKET][AC01_PCIE_MAX_ROOT_COMPLEX] =
  149. {
  150. { 0x0C, 0x0D, 0x01, 0x00, 0x02, 0x03, 0x04, 0x05 },
  151. { 0x10, 0x11, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B }
  152. };
  153. if (RootComplex->Socket < PLATFORM_CPU_MAX_SOCKET
  154. && RootComplex->ID < AC01_PCIE_MAX_ROOT_COMPLEX) {
  155. return Ac01BoardSegment[RootComplex->Socket][RootComplex->ID];
  156. }
  157. return (RootComplex->ID - 2);
  158. }