BoardPcieLib.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  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. /**
  31. Assert PERST of PCIe controller
  32. @param[in] RootComplex Root Complex instance.
  33. @param[in] PcieIndex PCIe controller index of input Root Complex.
  34. @param[in] IsPullToHigh Target status for the PERST.
  35. @retval RETURN_SUCCESS The operation is successful.
  36. @retval Others An error occurred.
  37. **/
  38. RETURN_STATUS
  39. EFIAPI
  40. BoardPcieAssertPerst (
  41. IN AC01_ROOT_COMPLEX *RootComplex,
  42. IN UINT8 PcieIndex,
  43. IN BOOLEAN IsPullToHigh
  44. )
  45. {
  46. UINT32 GpioGroupVal, Val, GpioIndex, GpioPin;
  47. if (!IsPullToHigh) {
  48. if (RootComplex->Type == RootComplexTypeA) {
  49. //
  50. // RootComplexTypeA: RootComplex->ID: 0->3 ; PcieIndex: 0->3
  51. //
  52. GpioGroupVal = RCA_MAX_PERST_GROUPVAL - PcieIndex
  53. - RootComplex->ID * MaxPcieControllerOfRootComplexA;
  54. } else {
  55. //
  56. // RootComplexTypeB: RootComplex->ID: 4->7 ; PcieIndex: 0->7
  57. //
  58. GpioGroupVal = RCB_MAX_PERST_GROUPVAL - PcieIndex
  59. - (RootComplex->ID - MaxRootComplexA) * MaxPcieControllerOfRootComplexB;
  60. }
  61. // Update the value of GPIO[16..21]. Corresponding PERST line will be decoded by CPLD.
  62. GpioPin = AC01_GPIO_PINS_PER_SOCKET * RootComplex->Socket + 16;
  63. for (GpioIndex = 0; GpioIndex < 6; GpioIndex++) {
  64. Val = (GpioGroupVal & 0x3F) & (1 << GpioIndex);
  65. if (Val == 0) {
  66. GpioModeConfig (GpioPin + GpioIndex, GpioConfigOutLow);
  67. } else {
  68. GpioModeConfig (GpioPin + GpioIndex, GpioConfigOutHigh);
  69. }
  70. }
  71. // Keep reset as low as 100 ms as specification
  72. MicroSecondDelay (PCIE_PERST_DELAY);
  73. } else {
  74. BoardPcieReleaseAllPerst (RootComplex->Socket);
  75. }
  76. return RETURN_SUCCESS;
  77. }
  78. /**
  79. Override the segment number for a root complex with a board specific number.
  80. @param[in] RootComplex Root Complex instance with properties.
  81. @retval Segment number corresponding to the input root complex.
  82. Default segment number is 0x0F.
  83. **/
  84. UINT16
  85. BoardPcieGetSegmentNumber (
  86. IN AC01_ROOT_COMPLEX *RootComplex
  87. )
  88. {
  89. UINT8 Ac01BoardSegment[PLATFORM_CPU_MAX_SOCKET][AC01_PCIE_MAX_ROOT_COMPLEX] =
  90. {
  91. { 0x0C, 0x0D, 0x01, 0x00, 0x02, 0x03, 0x04, 0x05 },
  92. { 0x10, 0x11, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B }
  93. };
  94. if (RootComplex->Socket < PLATFORM_CPU_MAX_SOCKET
  95. && RootComplex->ID < AC01_PCIE_MAX_ROOT_COMPLEX) {
  96. return Ac01BoardSegment[RootComplex->Socket][RootComplex->ID];
  97. }
  98. return DEFAULT_SEGMENT_NUMBER;
  99. }