1 /** @file 2 This driver does SA PCI Express ACPI table initialization. 3 4 Copyright (c) 2019 - 2020 Intel Corporation. All rights reserved. <BR> 5 6 SPDX-License-Identifier: BSD-2-Clause-Patent 7 **/ 8 9 #include "PciExpressInit.h" 10 #include <Library/ConfigBlockLib.h> 11 12 extern SYSTEM_AGENT_NVS_AREA_PROTOCOL mSaNvsAreaProtocol; 13 extern SA_CONFIG_HOB *mSaConfigHob; 14 15 /** 16 PCI Express Dxe Initialization. 17 Run before PCI Bus Init, where assignment of Bus, Memory, 18 and I/O Resources are assigned. 19 20 @param[in] SaPolicy - SA DXE Policy protocol 21 22 @retval EFI_SUCCESS - Pci Express successfully started and ready to be used 23 **/ 24 EFI_STATUS 25 PciExpressInit ( 26 IN SA_POLICY_PROTOCOL *SaPolicy 27 ) 28 { 29 EFI_STATUS Status; 30 PCIE_DXE_CONFIG *PcieDxeConfig; 31 MSR_BROADWELL_PKG_CST_CONFIG_CONTROL_REGISTER Msr; 32 33 Status = GetConfigBlock ((VOID *) SaPolicy, &gPcieDxeConfigGuid, (VOID *)&PcieDxeConfig); 34 ASSERT_EFI_ERROR (Status); 35 36 37 Msr.Uint64 = AsmReadMsr64 (MSR_BROADWELL_PKG_CST_CONFIG_CONTROL); 38 mSaNvsAreaProtocol.Area->PackageCstateLimit = (UINT8) Msr.Bits.Limit; 39 40 mSaNvsAreaProtocol.Area->PwrDnBundlesGlobalEnable = 0; 41 42 if (mSaConfigHob != NULL) { 43 mSaNvsAreaProtocol.Area->Peg0PowerDownUnusedBundles = mSaConfigHob->PowerDownUnusedBundles[0]; 44 mSaNvsAreaProtocol.Area->Peg1PowerDownUnusedBundles = mSaConfigHob->PowerDownUnusedBundles[1]; 45 mSaNvsAreaProtocol.Area->Peg2PowerDownUnusedBundles = mSaConfigHob->PowerDownUnusedBundles[2]; 46 if (SA_PEG_MAX_FUN > 3) { 47 mSaNvsAreaProtocol.Area->Peg3PowerDownUnusedBundles = mSaConfigHob->PowerDownUnusedBundles[3]; 48 } 49 } 50 /// 51 /// LTR/OBFF 52 /// 53 mSaNvsAreaProtocol.Area->Peg0LtrEnable = PcieDxeConfig->PegPwrOpt[0].LtrEnable; 54 mSaNvsAreaProtocol.Area->Peg0ObffEnable = PcieDxeConfig->PegPwrOpt[0].ObffEnable; 55 mSaNvsAreaProtocol.Area->Peg1LtrEnable = PcieDxeConfig->PegPwrOpt[1].LtrEnable; 56 mSaNvsAreaProtocol.Area->Peg1ObffEnable = PcieDxeConfig->PegPwrOpt[1].ObffEnable; 57 mSaNvsAreaProtocol.Area->Peg2LtrEnable = PcieDxeConfig->PegPwrOpt[2].LtrEnable; 58 mSaNvsAreaProtocol.Area->Peg2ObffEnable = PcieDxeConfig->PegPwrOpt[2].ObffEnable; 59 mSaNvsAreaProtocol.Area->PegLtrMaxSnoopLatency = LTR_MAX_SNOOP_LATENCY_VALUE; 60 mSaNvsAreaProtocol.Area->PegLtrMaxNoSnoopLatency = LTR_MAX_NON_SNOOP_LATENCY_VALUE; 61 62 return EFI_SUCCESS; 63 } 64 65 /** 66 Find the Offset to a given Capabilities ID 67 CAPID list: 68 0x01 = PCI Power Management Interface 69 0x04 = Slot Identification 70 0x05 = MSI Capability 71 0x10 = PCI Express Capability 72 73 @param[in] Segment - Pci Segment Number 74 @param[in] Bus - Pci Bus Number 75 @param[in] Device - Pci Device Number 76 @param[in] Function - Pci Function Number 77 @param[in] CapId - CAPID to search for 78 79 @retval 0 - CAPID not found 80 @retval Other - CAPID found, Offset of desired CAPID 81 **/ 82 UINT32 83 PcieFindCapId ( 84 IN UINT8 Segment, 85 IN UINT8 Bus, 86 IN UINT8 Device, 87 IN UINT8 Function, 88 IN UINT8 CapId 89 ) 90 { 91 UINT64 DeviceBaseAddress; 92 UINT8 CapHeader; 93 94 /// 95 /// Always start at Offset 0x34 96 /// 97 DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0); 98 CapHeader = PciSegmentRead8 (DeviceBaseAddress + PCI_CAPBILITY_POINTER_OFFSET); 99 if (CapHeader == 0xFF) { 100 return 0; 101 } 102 103 while (CapHeader != 0) { 104 /// 105 /// Bottom 2 bits of the pointers are reserved per PCI Local Bus Spec 2.2 106 /// 107 CapHeader &= ~(BIT1 + BIT0); 108 /// 109 /// Search for desired CapID 110 /// 111 if (PciSegmentRead8 (DeviceBaseAddress + CapHeader) == CapId) { 112 return CapHeader; 113 } 114 115 CapHeader = PciSegmentRead8 (DeviceBaseAddress + CapHeader + 1); 116 } 117 118 return 0; 119 } 120 121 /** 122 Search and return the offset of desired Pci Express Capability ID 123 CAPID list: 124 0x0001 = Advanced Error Rreporting Capability 125 0x0002 = Virtual Channel Capability 126 0x0003 = Device Serial Number Capability 127 0x0004 = Power Budgeting Capability 128 129 @param[in] Segment - Pci Segment Number 130 @param[in] Bus - Pci Bus Number 131 @param[in] Device - Pci Device Number 132 @param[in] Function - Pci Function Number 133 @param[in] CapId - Extended CAPID to search for 134 135 @retval 0 - CAPID not found 136 @retval Other - CAPID found, Offset of desired CAPID 137 **/ 138 UINT32 139 PcieFindExtendedCapId ( 140 IN UINT8 Segment, 141 IN UINT8 Bus, 142 IN UINT8 Device, 143 IN UINT8 Function, 144 IN UINT16 CapId 145 ) 146 { 147 UINT64 DeviceBaseAddress; 148 UINT16 CapHeaderOffset; 149 UINT16 CapHeaderId; 150 151 /// 152 /// Start to search at Offset 0x100 153 /// Get Capability Header 154 /// 155 DeviceBaseAddress = PCI_SEGMENT_LIB_ADDRESS (Segment, Bus, Device, Function, 0); 156 CapHeaderId = 0; 157 CapHeaderOffset = 0x100; 158 159 while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) { 160 /// 161 /// Search for desired CapID 162 /// 163 CapHeaderId = PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset); 164 if (CapHeaderId == CapId) { 165 return CapHeaderOffset; 166 } 167 168 CapHeaderOffset = (PciSegmentRead16 (DeviceBaseAddress + CapHeaderOffset + 2) >> 4); 169 } 170 171 return 0; 172 } 173