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