PchAcpi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452
  1. /** @file
  2. This is the driver that initializes the Intel PCH.
  3. Copyright (c) 2019 - 2020 Intel Corporation. All rights reserved. <BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include <Library/DebugLib.h>
  7. #include <Library/IoLib.h>
  8. #include <Library/BaseMemoryLib.h>
  9. #include <Library/HobLib.h>
  10. #include <Library/UefiBootServicesTableLib.h>
  11. #include <IndustryStandard/Pci.h>
  12. #include "PchInit.h"
  13. #include <Protocol/PchPolicy.h>
  14. #include <ConfigBlock/GpioDevConfig.h>
  15. #include <ConfigBlock/ScsConfig.h>
  16. #include <Library/AslUpdateLib.h>
  17. #include <Library/PchInfoLib.h>
  18. #include <Library/GpioLib.h>
  19. #include <Library/GpioNativeLib.h>
  20. #include <Library/PchCycleDecodingLib.h>
  21. #include <Library/PmcLib.h>
  22. #include <Library/PchSerialIoLib.h>
  23. #include <Library/PchGbeLib.h>
  24. #include <Private/PchRstHob.h>
  25. #include <Library/PchPcieRpLib.h>
  26. #include <Library/CpuPlatformLib.h>
  27. #include <Library/PciSegmentLib.h>
  28. #include <Library/SataLib.h>
  29. #include <Register/PchRegsSata.h>
  30. #include <TraceHubCommonConfig.h>
  31. #include <PchReservedResources.h>
  32. #include <Register/PchRegsTraceHub.h>
  33. #include <Library/ConfigBlockLib.h>
  34. //
  35. // Module variables
  36. //
  37. GLOBAL_REMOVE_IF_UNREFERENCED PCH_NVS_AREA_PROTOCOL mPchNvsAreaProtocol;
  38. /**
  39. Retrieve interrupt information about a PCH device from policy
  40. @param[in] Device PCI device number
  41. @retval PCH_DEVICE_INTERRUPT_CONFIG structure with device's interrupt information
  42. **/
  43. PCH_DEVICE_INTERRUPT_CONFIG
  44. GetInterruptPolicy (
  45. IN PCH_SERIAL_IO_CONTROLLER Device
  46. )
  47. {
  48. PCH_DEVICE_INTERRUPT_CONFIG EmptyRecord;
  49. UINT8 DevNum;
  50. UINT8 FuncNum;
  51. UINT8 Index;
  52. ZeroMem (&EmptyRecord, sizeof (PCH_DEVICE_INTERRUPT_CONFIG));
  53. DevNum = GetSerialIoDeviceNumber (Device);
  54. FuncNum = GetSerialIoFunctionNumber (Device);
  55. for (Index = 0; Index < mPchConfigHob->Interrupt.NumOfDevIntConfig; Index++) {
  56. if ((mPchConfigHob->Interrupt.DevIntConfig[Index].Device == DevNum) &&
  57. (mPchConfigHob->Interrupt.DevIntConfig[Index].Function == FuncNum)) {
  58. return mPchConfigHob->Interrupt.DevIntConfig[Index];
  59. }
  60. }
  61. return EmptyRecord;
  62. }
  63. /**
  64. Update ASL definitions for SerialIo devices.
  65. @retval EFI_SUCCESS The function completed successfully
  66. **/
  67. EFI_STATUS
  68. UpdateSerialIoAcpiData (
  69. VOID
  70. )
  71. {
  72. PCH_SERIAL_IO_CONTROLLER Index;
  73. for (Index = 0; Index < GetPchMaxSerialIoControllersNum (); Index++) {
  74. mPchNvsAreaProtocol.Area->SMD[Index] = mPchConfigHob->SerialIo.DevMode[Index];
  75. mPchNvsAreaProtocol.Area->SIR[Index] = (GetInterruptPolicy (Index)).Irq;
  76. mPchNvsAreaProtocol.Area->SB0[Index] = (UINT32) FindSerialIoBar (Index, 0);
  77. mPchNvsAreaProtocol.Area->SB1[Index] = (UINT32) FindSerialIoBar (Index, 1);
  78. }
  79. if (IsPchH ()) {
  80. mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C4] = PchSerialIoDisabled;
  81. mPchNvsAreaProtocol.Area->SMD[PchSerialIoIndexI2C5] = PchSerialIoDisabled;
  82. }
  83. return EFI_SUCCESS;
  84. }
  85. /**
  86. Update NVS Area after RST PCIe Storage Remapping and before Boot
  87. **/
  88. VOID
  89. PchUpdateNvsAreaAfterRemapping (
  90. VOID
  91. )
  92. {
  93. UINTN Index;
  94. VOID *Hob;
  95. PCH_RST_HOB *RstHob;
  96. Hob = GetFirstGuidHob (&gPchRstHobGuid);
  97. if (Hob == NULL) {
  98. DEBUG (( DEBUG_INFO , "PchUpdateNvsAreaAfterRemapping: cannot fetch RstHob" ));
  99. return;
  100. }
  101. RstHob = (PCH_RST_HOB *) GET_GUID_HOB_DATA (Hob);
  102. for (Index = 0; Index < PCH_MAX_RST_PCIE_STORAGE_CR; Index++) {
  103. mPchNvsAreaProtocol.Area->RstPcieStorageInterfaceType[Index] = RstHob->RstCrConfiguration[Index].DeviceInterface;
  104. mPchNvsAreaProtocol.Area->RstPcieStoragePmCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].PmCapPtr;
  105. mPchNvsAreaProtocol.Area->RstPcieStoragePcieCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].PcieCapPtr;
  106. mPchNvsAreaProtocol.Area->RstPcieStorageL1ssCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].L1ssCapPtr;
  107. mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl2[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl2;
  108. mPchNvsAreaProtocol.Area->RstPcieStorageEpL1ssControl1[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointL1ssControl1;
  109. mPchNvsAreaProtocol.Area->RstPcieStorageLtrCapPtr[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].LtrCapPtr;
  110. mPchNvsAreaProtocol.Area->RstPcieStorageEpLtrData[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLtrData;
  111. mPchNvsAreaProtocol.Area->RstPcieStorageEpLctlData16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointLctlData16;
  112. mPchNvsAreaProtocol.Area->RstPcieStorageEpDctlData16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctlData16;
  113. mPchNvsAreaProtocol.Area->RstPcieStorageEpDctl2Data16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].EndpointDctl2Data16;
  114. mPchNvsAreaProtocol.Area->RstPcieStorageRpDctl2Data16[Index] = RstHob->SavedRemapedDeviceConfigSpace[Index].RootPortDctl2Data16;
  115. mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBar[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBar;
  116. mPchNvsAreaProtocol.Area->RstPcieStorageUniqueTableBarValue[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixTableBarValue;
  117. mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBar[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBar;
  118. mPchNvsAreaProtocol.Area->RstPcieStorageUniquePbaBarValue[Index] = RstHob->RstCrConfiguration[Index].EndPointUniqueMsixPbaBarValue;
  119. mPchNvsAreaProtocol.Area->RstPcieStorageRootPortNum[Index] = RstHob->RstCrConfiguration[Index].RootPortNum;
  120. }
  121. }
  122. /**
  123. PCH ACPI initialization before Boot Sript Table is closed
  124. It update ACPI table and ACPI NVS area.
  125. @param[in] Event A pointer to the Event that triggered the callback.
  126. @param[in] Context A pointer to private data registered with the callback function.
  127. **/
  128. VOID
  129. EFIAPI
  130. PchAcpiOnEndOfDxe (
  131. IN EFI_EVENT Event,
  132. IN VOID *Context
  133. )
  134. {
  135. EFI_STATUS Status;
  136. DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() Start\n"));
  137. ///
  138. /// Closed the event to avoid call twice when launch shell
  139. ///
  140. gBS->CloseEvent (Event);
  141. //
  142. // Init HDA Audio ACPI tables
  143. //
  144. PchHdAudioAcpiInit ();
  145. //
  146. // Update ASL definitions for SerialIo devices.
  147. //
  148. UpdateSerialIoAcpiData ();
  149. UpdateCnviAcpiData ();
  150. //
  151. // Update Pch Nvs Area
  152. //
  153. Status = PchUpdateNvsArea ();
  154. if (EFI_ERROR (Status)) {
  155. return;
  156. }
  157. DEBUG ((DEBUG_INFO, "PchAcpiOnEndOfDxe() End\n"));
  158. return;
  159. }
  160. /**
  161. Initialize Pch acpi
  162. @param[in] ImageHandle Handle for the image of this driver
  163. @retval EFI_SUCCESS The function completed successfully
  164. @retval EFI_OUT_OF_RESOURCES Do not have enough resources to initialize the driver
  165. **/
  166. EFI_STATUS
  167. PchAcpiInit (
  168. IN EFI_HANDLE ImageHandle
  169. )
  170. {
  171. EFI_STATUS Status;
  172. EFI_EVENT EndOfDxeEvent;
  173. DEBUG ((DEBUG_INFO, "Install PCH NVS protocol\n"));
  174. Status = (gBS->AllocatePool) (EfiACPIMemoryNVS, sizeof (PCH_NVS_AREA), (VOID **) &mPchNvsAreaProtocol.Area);
  175. ASSERT_EFI_ERROR (Status);
  176. ZeroMem ((VOID *) mPchNvsAreaProtocol.Area, sizeof (PCH_NVS_AREA));
  177. Status = gBS->InstallMultipleProtocolInterfaces (
  178. &ImageHandle,
  179. &gPchNvsAreaProtocolGuid,
  180. &mPchNvsAreaProtocol,
  181. NULL
  182. );
  183. ASSERT_EFI_ERROR (Status);
  184. ///
  185. /// Update the NVS Area after RST PCIe Storage Remapping
  186. ///
  187. PchUpdateNvsAreaAfterRemapping ();
  188. //
  189. // Register an end of DXE event for PCH ACPI to do tasks before invoking any UEFI drivers,
  190. // applications, or connecting consoles,...
  191. //
  192. Status = gBS->CreateEventEx (
  193. EVT_NOTIFY_SIGNAL,
  194. TPL_CALLBACK,
  195. PchAcpiOnEndOfDxe,
  196. NULL,
  197. &gEfiEndOfDxeEventGroupGuid,
  198. &EndOfDxeEvent
  199. );
  200. ASSERT_EFI_ERROR (Status);
  201. return Status;
  202. }
  203. /**
  204. Update ASL object before Boot
  205. @retval EFI_STATUS
  206. @retval EFI_NOT_READY The Acpi protocols are not ready.
  207. **/
  208. EFI_STATUS
  209. PchUpdateNvsArea (
  210. VOID
  211. )
  212. {
  213. EFI_STATUS Status;
  214. UINTN Index;
  215. UINT32 HpetBaseAdress;
  216. GPIO_GROUP GroupToGpeDwX[3];
  217. UINT32 GroupDw[3];
  218. UINTN RpDev;
  219. UINTN RpFun;
  220. UINT32 Data32;
  221. PCH_POLICY_PROTOCOL *PchPolicy;
  222. PCH_GPIO_DXE_CONFIG *GpioDxeConfig;
  223. ///
  224. /// Get PCH Policy Protocol
  225. ///
  226. Status = gBS->LocateProtocol (&gPchPolicyProtocolGuid, NULL, (VOID **)&PchPolicy);
  227. ASSERT_EFI_ERROR (Status);
  228. ///
  229. /// Get GPIO DXE Config Block
  230. ///
  231. Status = GetConfigBlock ((VOID *)PchPolicy, &gGpioDxeConfigGuid, (VOID *)&GpioDxeConfig);
  232. ASSERT_EFI_ERROR (Status);
  233. //
  234. // Update ASL PCIE port address according to root port device and function
  235. //
  236. for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
  237. Status = GetPchPcieRpDevFun (Index, &RpDev, &RpFun);
  238. ASSERT_EFI_ERROR (Status);
  239. Data32 = ((UINT8) RpDev << 16) | (UINT8) RpFun;
  240. mPchNvsAreaProtocol.Area->RpAddress[Index] = Data32;
  241. //
  242. // Update Maximum Snoop Latency and Maximum No-Snoop Latency values for PCIE
  243. //
  244. mPchNvsAreaProtocol.Area->PcieLtrMaxSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].LtrMaxSnoopLatency;
  245. mPchNvsAreaProtocol.Area->PcieLtrMaxNoSnoopLatency[Index] = mPchConfigHob->PcieRp.RootPort[Index].LtrMaxNoSnoopLatency;
  246. }
  247. //
  248. // Update PCHS.
  249. //
  250. mPchNvsAreaProtocol.Area->PchSeries = PchSeries ();
  251. //
  252. // Update PCHG.
  253. //
  254. mPchNvsAreaProtocol.Area->PchGeneration = (UINT16) PchGeneration ();
  255. //
  256. // Update PSTP.
  257. //
  258. mPchNvsAreaProtocol.Area->PchStepping = (UINT16) PchStepping ();
  259. //
  260. // Update HPET base address.
  261. //
  262. PchHpetBaseGet (&HpetBaseAdress);
  263. mPchNvsAreaProtocol.Area->HPTE = TRUE; // @todo remove the NVS, since it's always enabled.
  264. mPchNvsAreaProtocol.Area->HPTB = HpetBaseAdress;
  265. //
  266. // Update SBREG_BAR.
  267. //
  268. mPchNvsAreaProtocol.Area->SBRG = PCH_PCR_BASE_ADDRESS;
  269. //
  270. // Update PMC ACPIBASE and PWRMBASE
  271. //
  272. mPchNvsAreaProtocol.Area->PMBS = PmcGetAcpiBase ();
  273. mPchNvsAreaProtocol.Area->PWRM = PmcGetPwrmBase ();
  274. //
  275. // Update GPIO device ACPI variables
  276. //
  277. mPchNvsAreaProtocol.Area->SGIR = mPchConfigHob->Interrupt.GpioIrqRoute;
  278. mPchNvsAreaProtocol.Area->GPHD = (UINT8)GpioDxeConfig->HideGpioAcpiDevice;
  279. //
  280. // Update GPP_X to GPE_DWX mapping.
  281. //
  282. GpioGetGroupDwToGpeDwX (
  283. &GroupToGpeDwX[0], &GroupDw[0],
  284. &GroupToGpeDwX[1], &GroupDw[1],
  285. &GroupToGpeDwX[2], &GroupDw[2]
  286. );
  287. //
  288. // GEI0/1/2 and GED0/1/2 are objects for informing how GPIO groups are mapped to GPE0.
  289. // If Group is mapped to 1-Tier GPE information is also stored on what Group DW
  290. // is mapped to GPE_DWx. Because GPE_DWx register is 32 bits large if groups have more than
  291. // 32 pads only part of it can be mapped.
  292. //
  293. // GEIx - GroupIndex mapped to GPE0_DWx
  294. // GEDx - DoubleWorld part of Group: 0 - pins 31-0, 1 - pins 63-32, ...
  295. //
  296. mPchNvsAreaProtocol.Area->GEI0 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[0]);
  297. mPchNvsAreaProtocol.Area->GEI1 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[1]);
  298. mPchNvsAreaProtocol.Area->GEI2 = (UINT8) GpioGetGroupIndexFromGroup (GroupToGpeDwX[2]);
  299. mPchNvsAreaProtocol.Area->GED0 = (UINT8) GroupDw[0];
  300. mPchNvsAreaProtocol.Area->GED1 = (UINT8) GroupDw[1];
  301. mPchNvsAreaProtocol.Area->GED2 = (UINT8) GroupDw[2];
  302. //
  303. // SCS Configuration
  304. //
  305. // Update eMMC HS400 mode enablement
  306. //
  307. mPchNvsAreaProtocol.Area->EMH4 = (UINT8) mPchConfigHob->Scs.ScsEmmcHs400Enabled;
  308. mPchNvsAreaProtocol.Area->EmmcEnabled = (UINT8) mPchConfigHob->Scs.ScsEmmcEnabled;
  309. //
  310. // Update eMMC Driver Strength
  311. // Per eMMC 5.01 JEDEC Specification (JESD84-B50.1, Table 186)
  312. // Nominal Impedance - Driver Type Values:
  313. // 50 Ohm 0x0
  314. // 33 Ohm 0x1
  315. // 40 Ohm 0x4
  316. //
  317. switch (mPchConfigHob->Scs.ScsEmmcHs400DriverStrength) {
  318. case DriverStrength33Ohm:
  319. mPchNvsAreaProtocol.Area->EMDS = 0x1;
  320. break;
  321. case DriverStrength40Ohm:
  322. mPchNvsAreaProtocol.Area->EMDS = 0x4;
  323. break;
  324. case DriverStrength50Ohm:
  325. default:
  326. mPchNvsAreaProtocol.Area->EMDS = 0x0;
  327. }
  328. mPchNvsAreaProtocol.Area->SdPowerEnableActiveHigh = (UINT8) mPchConfigHob->Scs.ScsSdPowerEnableActiveHigh;
  329. mPchNvsAreaProtocol.Area->SdCardEnabled = (UINT8) mPchConfigHob->Scs.ScsSdCardEnabled;
  330. //
  331. // SATA configuration.
  332. //
  333. if (PciSegmentRead16 (GetSataRegBase (SATA_1_CONTROLLER_INDEX) + PCI_DEVICE_ID_OFFSET) == 0xFFFF) {
  334. mPchNvsAreaProtocol.Area->SataPortPresence = 0;
  335. } else {
  336. mPchNvsAreaProtocol.Area->SataPortPresence = PciSegmentRead8 (GetSataRegBase (SATA_1_CONTROLLER_INDEX) + R_SATA_CFG_PCS + 2);
  337. }
  338. //
  339. // CPU SKU
  340. //
  341. mPchNvsAreaProtocol.Area->CpuSku = GetCpuSku ();
  342. mPchNvsAreaProtocol.Area->SlpS0VmRuntimeControl = (UINT8)mPchConfigHob->Pm.SlpS0VmRuntimeControl;
  343. mPchNvsAreaProtocol.Area->SlpS0Vm070VSupport = (UINT8)mPchConfigHob->Pm.SlpS0Vm070VSupport;
  344. mPchNvsAreaProtocol.Area->SlpS0Vm075VSupport = (UINT8)mPchConfigHob->Pm.SlpS0Vm075VSupport;
  345. mPchNvsAreaProtocol.Area->PsOnEnable = (UINT8)mPchConfigHob->Pm.PsOnEnable;
  346. for (Index = 0; Index < GetPchMaxPciePortNum (); Index++) {
  347. mPchNvsAreaProtocol.Area->LtrEnable[Index] = (UINT8)mPchConfigHob->PcieRp.RootPort[Index].LtrEnable;
  348. }
  349. mPchNvsAreaProtocol.Area->GBES = PchIsGbePresent ();
  350. //
  351. // Update PCH Trace Hub Mode
  352. //
  353. mPchNvsAreaProtocol.Area->PchTraceHubMode = (UINT8) mPchConfigHob->PchTraceHub.PchTraceHubMode;
  354. //
  355. // if SCRPD0[24] is set, force TH to be host debugger mode.
  356. //
  357. if (MmioRead32 (PCH_TRACE_HUB_MTB_BASE_ADDRESS) != 0xFFFFFFFF) {
  358. if (MmioRead32 (PCH_TRACE_HUB_MTB_BASE_ADDRESS + R_TRACE_HUB_MEM_CSR_MTB_SCRATCHPAD0) & BIT24) {
  359. mPchNvsAreaProtocol.Area->PchTraceHubMode = TraceHubModeHostDebugger;
  360. }
  361. }
  362. //
  363. // Update TWMB, Temp memory base address
  364. //
  365. mPchNvsAreaProtocol.Area->TempRsvdMemBase = (UINT32) PcdGet32 (PcdSiliconInitTempMemBaseAddr);
  366. return Status;
  367. }
  368. /**
  369. Initialize PCH Nvs Area opeartion region.
  370. **/
  371. VOID
  372. PatchPchNvsAreaAddress (
  373. VOID
  374. )
  375. {
  376. EFI_STATUS Status;
  377. UINT32 Address;
  378. UINT16 Length;
  379. Status = InitializeAslUpdateLib ();
  380. ASSERT_EFI_ERROR (Status);
  381. Address = (UINT32) (UINTN) mPchNvsAreaProtocol.Area;
  382. Length = (UINT16) sizeof (PCH_NVS_AREA);
  383. DEBUG ((DEBUG_INFO, "PatchPchNvsAreaAddress: PCH NVS Address %x Length %x\n", Address, Length));
  384. Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','B'), &Address, sizeof (Address));
  385. ASSERT_EFI_ERROR (Status);
  386. Status = UpdateNameAslCode (SIGNATURE_32 ('P','N','V','L'), &Length, sizeof (Length));
  387. ASSERT_EFI_ERROR (Status);
  388. }