96BoardsI2cDxe.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. /** @file
  2. Copyright (c) 2018, Linaro, Ltd. All rights reserved.<BR>
  3. SPDX-License-Identifier: BSD-2-Clause-Patent
  4. **/
  5. #include <PiDxe.h>
  6. #include <Library/BaseMemoryLib.h>
  7. #include <Library/DebugLib.h>
  8. #include <Library/UefiBootServicesTableLib.h>
  9. #include <Library/UefiLib.h>
  10. #include <Protocol/I2cBusConfigurationManagement.h>
  11. #include <Protocol/I2cEnumerate.h>
  12. #include <Protocol/I2cMaster.h>
  13. #include <Protocol/Mezzanine.h>
  14. STATIC MEZZANINE_PROTOCOL *mMezzanine;
  15. typedef struct {
  16. EFI_I2C_ENUMERATE_PROTOCOL I2cEnumerate;
  17. EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL I2cConfigManagement;
  18. EFI_HANDLE I2cMasterHandle;
  19. UINT32 BusFrequency;
  20. UINTN NumDevices;
  21. CONST EFI_I2C_DEVICE *Devices;
  22. } I2C_BUS;
  23. STATIC
  24. EFI_STATUS
  25. EFIAPI
  26. I2cEnumerate (
  27. IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This,
  28. IN OUT CONST EFI_I2C_DEVICE **Device
  29. )
  30. {
  31. I2C_BUS *Bus;
  32. if (Device == NULL) {
  33. return EFI_INVALID_PARAMETER;
  34. }
  35. Bus = BASE_CR (This, I2C_BUS, I2cEnumerate);
  36. if (Bus->NumDevices == 0 ||
  37. (Bus->NumDevices > 0 && *Device == &Bus->Devices[Bus->NumDevices - 1])) {
  38. *Device = NULL;
  39. } else if (*Device == NULL) {
  40. *Device = &Bus->Devices[0];
  41. } else if (Bus->NumDevices > 1 &&
  42. *Device >= &Bus->Devices[0] &&
  43. *Device < &Bus->Devices[Bus->NumDevices - 1]) {
  44. ++*Device;
  45. } else {
  46. return EFI_NO_MAPPING;
  47. }
  48. return EFI_SUCCESS;
  49. }
  50. STATIC
  51. EFI_STATUS
  52. EFIAPI
  53. I2cGetBusFrequency (
  54. IN CONST EFI_I2C_ENUMERATE_PROTOCOL *This,
  55. IN UINTN I2cBusConfiguration,
  56. OUT UINTN *BusClockHertz
  57. )
  58. {
  59. I2C_BUS *Bus;
  60. if (BusClockHertz == NULL) {
  61. return EFI_INVALID_PARAMETER;
  62. }
  63. if (I2cBusConfiguration > 0) {
  64. return EFI_NO_MAPPING;
  65. }
  66. Bus = BASE_CR (This, I2C_BUS, I2cEnumerate);
  67. *BusClockHertz = Bus->BusFrequency;
  68. return EFI_SUCCESS;
  69. }
  70. STATIC
  71. EFI_STATUS
  72. EFIAPI
  73. EnableI2cBusConfiguration (
  74. IN CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *This,
  75. IN UINTN I2cBusConfiguration,
  76. IN EFI_EVENT Event OPTIONAL,
  77. IN EFI_STATUS *I2cStatus OPTIONAL
  78. )
  79. {
  80. EFI_I2C_MASTER_PROTOCOL *I2cMaster;
  81. EFI_STATUS Status;
  82. UINTN BusClockHertz;
  83. I2C_BUS *Bus;
  84. if (I2cBusConfiguration > 0) {
  85. return EFI_NO_MAPPING;
  86. }
  87. Bus = BASE_CR (This, I2C_BUS, I2cConfigManagement);
  88. Status = gBS->HandleProtocol (Bus->I2cMasterHandle,
  89. &gEfiI2cMasterProtocolGuid, (VOID **)&I2cMaster);
  90. if (EFI_ERROR (Status)) {
  91. DEBUG ((DEBUG_ERROR, "%a: gBS->HandleProtocol() failed - %r\n",
  92. __FUNCTION__, Status));
  93. return Status;
  94. }
  95. BusClockHertz = Bus->BusFrequency;
  96. Status = I2cMaster->SetBusFrequency (I2cMaster, &BusClockHertz);
  97. if (EFI_ERROR (Status)) {
  98. DEBUG ((DEBUG_ERROR, "%a: I2cMaster->SetBusFrequency() failed - %r\n",
  99. __FUNCTION__, Status));
  100. return Status;
  101. }
  102. if (Event != NULL) {
  103. *I2cStatus = EFI_SUCCESS;
  104. gBS->SignalEvent (Event);
  105. }
  106. return EFI_SUCCESS;
  107. }
  108. STATIC I2C_BUS mI2cBus0 = {
  109. { I2cEnumerate, I2cGetBusFrequency },
  110. { EnableI2cBusConfiguration },
  111. NULL,
  112. FixedPcdGet32 (PcdI2c0BusFrequencyHz),
  113. 0,
  114. NULL,
  115. };
  116. STATIC I2C_BUS mI2cBus1 = {
  117. { I2cEnumerate, I2cGetBusFrequency },
  118. { EnableI2cBusConfiguration },
  119. NULL,
  120. FixedPcdGet32 (PcdI2c1BusFrequencyHz),
  121. 0,
  122. NULL,
  123. };
  124. STATIC
  125. VOID
  126. RegisterI2cBus (
  127. IN EFI_GUID *Guid,
  128. IN I2C_BUS *I2cBus,
  129. IN UINTN NumDevices,
  130. IN CONST EFI_I2C_DEVICE *Devices
  131. )
  132. {
  133. EFI_STATUS Status;
  134. UINTN BufferSize;
  135. BufferSize = sizeof (EFI_HANDLE);
  136. Status = gBS->LocateHandle (ByProtocol, Guid, NULL, &BufferSize,
  137. &I2cBus->I2cMasterHandle);
  138. if (EFI_ERROR (Status)) {
  139. DEBUG ((DEBUG_INFO, "%a: gBS->LocateHandle() failed - %r\n", __FUNCTION__,
  140. Status));
  141. return;
  142. }
  143. I2cBus->NumDevices = NumDevices;
  144. I2cBus->Devices = Devices;
  145. Status = gBS->InstallMultipleProtocolInterfaces (&I2cBus->I2cMasterHandle,
  146. &gEfiI2cEnumerateProtocolGuid,
  147. &I2cBus->I2cEnumerate,
  148. &gEfiI2cBusConfigurationManagementProtocolGuid,
  149. &I2cBus->I2cConfigManagement,
  150. NULL);
  151. ASSERT_EFI_ERROR (Status);
  152. }
  153. STATIC
  154. VOID
  155. EFIAPI
  156. OnEndOfDxe (
  157. IN EFI_EVENT Event,
  158. IN VOID *Context
  159. )
  160. {
  161. gBS->CloseEvent (Event);
  162. gBS->ConnectController (mI2cBus0.I2cMasterHandle, NULL, NULL, TRUE);
  163. gBS->ConnectController (mI2cBus1.I2cMasterHandle, NULL, NULL, TRUE);
  164. }
  165. EFI_STATUS
  166. EFIAPI
  167. EntryPoint (
  168. IN EFI_HANDLE ImageHandle,
  169. IN EFI_SYSTEM_TABLE *SystemTable
  170. )
  171. {
  172. EFI_STATUS Status;
  173. EFI_EVENT EndOfDxeEvent;
  174. Status = gBS->LocateProtocol (&g96BoardsMezzanineProtocolGuid, NULL,
  175. (VOID **)&mMezzanine);
  176. ASSERT_EFI_ERROR (Status);
  177. RegisterI2cBus (&g96BoardsI2c0MasterGuid, &mI2cBus0,
  178. mMezzanine->I2c0NumDevices, mMezzanine->I2c0DeviceArray);
  179. RegisterI2cBus (&g96BoardsI2c1MasterGuid, &mI2cBus1,
  180. mMezzanine->I2c1NumDevices, mMezzanine->I2c1DeviceArray);
  181. Status = gBS->CreateEventEx (EVT_NOTIFY_SIGNAL, TPL_CALLBACK, OnEndOfDxe,
  182. NULL, &gEfiEndOfDxeEventGroupGuid, &EndOfDxeEvent);
  183. ASSERT_EFI_ERROR (Status);
  184. return EFI_SUCCESS;
  185. }