I2cDebugPortProtocol.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  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. UINT8 CurrentSize;
  35. UINT8 DdcBusPinPair;
  36. if (Count <= 0) {
  37. return EFI_INVALID_PARAMETER;
  38. }
  39. if (Buffer == NULL) {
  40. return EFI_INVALID_PARAMETER;
  41. }
  42. Status = GetGmbusBusPinPairForI2cDebugPort (&DdcBusPinPair);
  43. if (EFI_ERROR (Status)) {
  44. return Status;
  45. }
  46. RaiseTplForI2cDebugPortAccess ();
  47. for (Index = 0; Index < Count; Index += I2C_DEBUG_PORT_MAX_DATA_SIZE) {
  48. MicroSecondDelay (3000); //3ms stall to let the BusPirate catch up
  49. if ((Index + I2C_DEBUG_PORT_MAX_DATA_SIZE) >= Count) {
  50. CurrentSize = (UINT8) (Count - Index);
  51. } else {
  52. CurrentSize = I2C_DEBUG_PORT_MAX_DATA_SIZE;
  53. }
  54. WriteBuffer[0] = (I2C_DEBUG_PORT_WRITE_COMMAND << I2C_DEBUG_PORT_COMMAND_BIT_POSITION) |
  55. (CurrentSize & I2C_DEBUG_PORT_DATA_SIZE_BIT_MASK);
  56. CopyMem (&(WriteBuffer[1]), &(Buffer[Index]), CurrentSize);
  57. Status = GmbusWrite (DdcBusPinPair, I2C_DEBUG_PORT_WRITE_DEVICE_ADDRESS, TRUE, CurrentSize + 1, &(WriteBuffer[0]));
  58. if (EFI_ERROR (Status)) {
  59. break;
  60. }
  61. }
  62. RestoreTplAfterI2cDebugPortAccess ();
  63. return Status;
  64. }
  65. /**
  66. Reads data from the I2C debug port
  67. @param[out] Buffer - The memory buffer to return the read data.
  68. @param[in, out] Count - The number of bytes to read from the I2C debug port.
  69. On output, the number of bytes actually read.
  70. @retval EFI_SUCCESS - The data was successfully read.
  71. @retval EFI_INVALID_PARAMETER - One of the following conditions:
  72. * ByteCount is 0
  73. * Buffer is NULL
  74. @retval EFI_TIMEOUT - The I2C controller did not respond within the required timeout period.
  75. @retval EFI_DEVICE_ERROR - An error occurred while accessing the I2C controller.
  76. **/
  77. EFI_STATUS
  78. I2cDebugPortRead (
  79. OUT UINT8 *Buffer,
  80. IN OUT UINT32 *Count
  81. )
  82. {
  83. EFI_STATUS Status;
  84. UINT32 Index;
  85. UINT32 BytesRead;
  86. UINT32 CurrentSize;
  87. UINT8 DdcBusPinPair;
  88. UINT8 GmbusIndexData;
  89. BytesRead = 0;
  90. if ((*Count) <= 0) {
  91. return EFI_INVALID_PARAMETER;
  92. }
  93. if (Buffer == NULL) {
  94. return EFI_INVALID_PARAMETER;
  95. }
  96. Status = GetGmbusBusPinPairForI2cDebugPort (&DdcBusPinPair);
  97. if (EFI_ERROR (Status)) {
  98. return Status;
  99. }
  100. RaiseTplForI2cDebugPortAccess ();
  101. for (Index = 0; Index < (*Count); Index += I2C_DEBUG_PORT_MAX_DATA_SIZE) {
  102. MicroSecondDelay (3000); //3ms stall to let the BusPirate catch up
  103. if ((Index + I2C_DEBUG_PORT_MAX_DATA_SIZE) >= (*Count)) {
  104. CurrentSize = (*Count) - Index;
  105. } else {
  106. CurrentSize = I2C_DEBUG_PORT_MAX_DATA_SIZE;
  107. }
  108. GmbusIndexData = (I2C_DEBUG_PORT_READ_COMMAND << I2C_DEBUG_PORT_COMMAND_BIT_POSITION) |
  109. (CurrentSize & I2C_DEBUG_PORT_DATA_SIZE_BIT_MASK);
  110. Status = GmbusRead (
  111. DdcBusPinPair,
  112. I2C_DEBUG_PORT_READ_DEVICE_ADDRESS,
  113. TRUE,
  114. TRUE,
  115. GmbusIndexData,
  116. &CurrentSize,
  117. &(Buffer[Index])
  118. );
  119. if (EFI_ERROR (Status)) {
  120. break;
  121. }
  122. BytesRead += CurrentSize;
  123. if (((Index + I2C_DEBUG_PORT_MAX_DATA_SIZE) < (*Count)) && (CurrentSize < I2C_DEBUG_PORT_MAX_DATA_SIZE)) {
  124. break;
  125. }
  126. }
  127. RestoreTplAfterI2cDebugPortAccess ();
  128. (*Count) = BytesRead;
  129. return Status;
  130. }
  131. /**
  132. Queries the I2C debug port to see if there are any data waiting to be read
  133. @param[out] NumberOfBytesInFifoBuffer - The number of bytes sitting in the I2C debug port's
  134. FIFO buffer waiting to be read
  135. @retval EFI_SUCCESS - The I2C debug port was successfully queried
  136. @retval EFI_INVALID_PARAMETER - One of the following conditions:
  137. * NumberOfBytesInFifoBuffer is NULL
  138. @retval EFI_TIMEOUT - The I2C controller did not respond within the required timeout period.
  139. @retval EFI_DEVICE_ERROR - An error occurred while accessing the I2C controller.
  140. **/
  141. EFI_STATUS
  142. I2cDebugPortReadyToRead (
  143. OUT UINT8 *NumberOfBytesInFifoBuffer
  144. )
  145. {
  146. EFI_STATUS Status;
  147. UINT32 BytesRead;
  148. UINT8 DdcBusPinPair;
  149. UINT8 GmbusIndexData;
  150. BytesRead = 1;
  151. if (NumberOfBytesInFifoBuffer == NULL) {
  152. return EFI_INVALID_PARAMETER;
  153. }
  154. Status = GetGmbusBusPinPairForI2cDebugPort (&DdcBusPinPair);
  155. if (EFI_ERROR (Status)) {
  156. return Status;
  157. }
  158. MicroSecondDelay (3000); //3ms stall to let the BusPirate catch up
  159. GmbusIndexData = (I2C_DEBUG_PORT_READY_TO_READ_COMMAND << I2C_DEBUG_PORT_COMMAND_BIT_POSITION) |
  160. (1 & I2C_DEBUG_PORT_DATA_SIZE_BIT_MASK); //READY_TO_READ always returns 1 byte
  161. RaiseTplForI2cDebugPortAccess ();
  162. Status = GmbusRead (DdcBusPinPair, I2C_DEBUG_PORT_READ_DEVICE_ADDRESS, TRUE, TRUE, GmbusIndexData, &BytesRead, NumberOfBytesInFifoBuffer);
  163. if (EFI_ERROR (Status)) {
  164. return Status;
  165. }
  166. RestoreTplAfterI2cDebugPortAccess ();
  167. if (BytesRead != 1) {
  168. Status = EFI_DEVICE_ERROR;
  169. }
  170. return Status;
  171. }