I2cDebugPortProtocol.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. /** @file
  2. I2C Debug Port Protocol Implementation
  3. Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Base.h>
  7. #include <Library/BaseLib.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/PcdLib.h>
  10. #include <Library/TimerLib.h>
  11. #include <IgfxI2c.h>
  12. #include <Gmbus.h>
  13. #include <I2cDebugPortProtocol.h>
  14. /**
  15. Writes data to the I2C debug port
  16. @param[in] Buffer - The data to be written to the I2C debug port.
  17. @param[in] Count - The number of bytes to write to the I2C debug port.
  18. @retval EFI_SUCCESS - The data was successfully written.
  19. @retval EFI_INVALID_PARAMETER - One of the following conditions:
  20. * ByteCount is 0
  21. * Buffer is NULL
  22. @retval EFI_TIMEOUT - The I2C controller did not respond within the required timeout period.
  23. @retval EFI_DEVICE_ERROR - An error occurred while accessing the I2C controller.
  24. **/
  25. EFI_STATUS
  26. I2cDebugPortWrite (
  27. IN UINT8 *Buffer,
  28. IN UINT32 Count
  29. )
  30. {
  31. UINT8 WriteBuffer[I2C_DEBUG_PORT_MAX_DATA_SIZE + 1];
  32. EFI_STATUS Status;
  33. UINT32 Index;
  34. UINT32 ImplementationDelayUs;
  35. UINT8 CurrentSize;
  36. UINT8 DdcBusPinPair;
  37. if (Count <= 0) {
  38. return EFI_INVALID_PARAMETER;
  39. }
  40. if (Buffer == NULL) {
  41. return EFI_INVALID_PARAMETER;
  42. }
  43. Status = GetGmbusBusPinPairForI2cDebugPort (&DdcBusPinPair);
  44. if (EFI_ERROR (Status)) {
  45. return Status;
  46. }
  47. ImplementationDelayUs = FixedPcdGet32 (PcdI2cHdmiDebugPortPacketStallUs); //BP: 3ms stall to catch up
  48. RaiseTplForI2cDebugPortAccess ();
  49. for (Index = 0; Index < Count; Index += I2C_DEBUG_PORT_MAX_DATA_SIZE) {
  50. MicroSecondDelay (ImplementationDelayUs);
  51. if ((Index + I2C_DEBUG_PORT_MAX_DATA_SIZE) >= Count) {
  52. CurrentSize = (UINT8) (Count - Index);
  53. } else {
  54. CurrentSize = I2C_DEBUG_PORT_MAX_DATA_SIZE;
  55. }
  56. WriteBuffer[0] = (I2C_DEBUG_PORT_WRITE_COMMAND << I2C_DEBUG_PORT_COMMAND_BIT_POSITION) |
  57. (CurrentSize & I2C_DEBUG_PORT_DATA_SIZE_BIT_MASK);
  58. CopyMem (&(WriteBuffer[1]), &(Buffer[Index]), CurrentSize);
  59. Status = GmbusWrite (DdcBusPinPair, I2C_DEBUG_PORT_WRITE_DEVICE_ADDRESS, TRUE, CurrentSize + 1, &(WriteBuffer[0]));
  60. if (EFI_ERROR (Status)) {
  61. break;
  62. }
  63. }
  64. RestoreTplAfterI2cDebugPortAccess ();
  65. return Status;
  66. }
  67. /**
  68. Reads data from the I2C debug port
  69. @param[out] Buffer - The memory buffer to return the read data.
  70. @param[in, out] Count - The number of bytes to read from the I2C debug port.
  71. On output, the number of bytes actually read.
  72. @retval EFI_SUCCESS - The data was successfully read.
  73. @retval EFI_INVALID_PARAMETER - One of the following conditions:
  74. * ByteCount is 0
  75. * Buffer is NULL
  76. @retval EFI_TIMEOUT - The I2C controller did not respond within the required timeout period.
  77. @retval EFI_DEVICE_ERROR - An error occurred while accessing the I2C controller.
  78. **/
  79. EFI_STATUS
  80. I2cDebugPortRead (
  81. OUT UINT8 *Buffer,
  82. IN OUT UINT32 *Count
  83. )
  84. {
  85. EFI_STATUS Status;
  86. UINT32 Index;
  87. UINT32 BytesRead;
  88. UINT32 ImplementationDelayUs;
  89. UINT32 CurrentSize;
  90. UINT8 DdcBusPinPair;
  91. UINT8 GmbusIndexData;
  92. BytesRead = 0;
  93. if ((*Count) <= 0) {
  94. return EFI_INVALID_PARAMETER;
  95. }
  96. if (Buffer == NULL) {
  97. return EFI_INVALID_PARAMETER;
  98. }
  99. Status = GetGmbusBusPinPairForI2cDebugPort (&DdcBusPinPair);
  100. if (EFI_ERROR (Status)) {
  101. return Status;
  102. }
  103. ImplementationDelayUs = FixedPcdGet32 (PcdI2cHdmiDebugPortPacketStallUs); //BP: 3ms stall to catch up
  104. RaiseTplForI2cDebugPortAccess ();
  105. for (Index = 0; Index < (*Count); Index += I2C_DEBUG_PORT_MAX_DATA_SIZE) {
  106. MicroSecondDelay (ImplementationDelayUs);
  107. if ((Index + I2C_DEBUG_PORT_MAX_DATA_SIZE) >= (*Count)) {
  108. CurrentSize = (*Count) - Index;
  109. } else {
  110. CurrentSize = I2C_DEBUG_PORT_MAX_DATA_SIZE;
  111. }
  112. GmbusIndexData = (I2C_DEBUG_PORT_READ_COMMAND << I2C_DEBUG_PORT_COMMAND_BIT_POSITION) |
  113. (CurrentSize & I2C_DEBUG_PORT_DATA_SIZE_BIT_MASK);
  114. Status = GmbusRead (
  115. DdcBusPinPair,
  116. I2C_DEBUG_PORT_READ_DEVICE_ADDRESS,
  117. TRUE,
  118. TRUE,
  119. GmbusIndexData,
  120. &CurrentSize,
  121. &(Buffer[Index])
  122. );
  123. if (EFI_ERROR (Status)) {
  124. break;
  125. }
  126. BytesRead += CurrentSize;
  127. if (((Index + I2C_DEBUG_PORT_MAX_DATA_SIZE) < (*Count)) && (CurrentSize < I2C_DEBUG_PORT_MAX_DATA_SIZE)) {
  128. break;
  129. }
  130. }
  131. RestoreTplAfterI2cDebugPortAccess ();
  132. (*Count) = BytesRead;
  133. return Status;
  134. }
  135. /**
  136. Queries the I2C debug port to see if there are any data waiting to be read
  137. @param[out] NumberOfBytesInFifoBuffer - The number of bytes sitting in the I2C debug port's
  138. FIFO buffer waiting to be read
  139. @retval EFI_SUCCESS - The I2C debug port was successfully queried
  140. @retval EFI_INVALID_PARAMETER - One of the following conditions:
  141. * NumberOfBytesInFifoBuffer is NULL
  142. @retval EFI_TIMEOUT - The I2C controller did not respond within the required timeout period.
  143. @retval EFI_DEVICE_ERROR - An error occurred while accessing the I2C controller.
  144. **/
  145. EFI_STATUS
  146. I2cDebugPortReadyToRead (
  147. OUT UINT8 *NumberOfBytesInFifoBuffer
  148. )
  149. {
  150. EFI_STATUS Status;
  151. UINT32 BytesRead;
  152. UINT8 DdcBusPinPair;
  153. UINT32 ImplementationDelayUs;
  154. UINT8 GmbusIndexData;
  155. BytesRead = 1;
  156. if (NumberOfBytesInFifoBuffer == NULL) {
  157. return EFI_INVALID_PARAMETER;
  158. }
  159. Status = GetGmbusBusPinPairForI2cDebugPort (&DdcBusPinPair);
  160. if (EFI_ERROR (Status)) {
  161. return Status;
  162. }
  163. ImplementationDelayUs = FixedPcdGet32 (PcdI2cHdmiDebugPortPacketStallUs); //BP: 3ms stall to catch up
  164. MicroSecondDelay (ImplementationDelayUs);
  165. GmbusIndexData = (I2C_DEBUG_PORT_READY_TO_READ_COMMAND << I2C_DEBUG_PORT_COMMAND_BIT_POSITION) |
  166. (1 & I2C_DEBUG_PORT_DATA_SIZE_BIT_MASK); //READY_TO_READ always returns 1 byte
  167. RaiseTplForI2cDebugPortAccess ();
  168. Status = GmbusRead (DdcBusPinPair, I2C_DEBUG_PORT_READ_DEVICE_ADDRESS, TRUE, TRUE, GmbusIndexData, &BytesRead, NumberOfBytesInFifoBuffer);
  169. if (EFI_ERROR (Status)) {
  170. return Status;
  171. }
  172. RestoreTplAfterI2cDebugPortAccess ();
  173. if (BytesRead != 1) {
  174. Status = EFI_DEVICE_ERROR;
  175. }
  176. return Status;
  177. }