blob: ff425c5c16354c227448a3f7d917eb242801593e [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * PCIe utility. Various supporting functions.
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
12 * @e \$Revision: 38931 $ @e \$Date: 2010-10-01 15:50:05 -0700 (Fri, 01 Oct 2010) $
13 *
14 */
15/*
16 *****************************************************************************
17 *
18 * Copyright (c) 2011, Advanced Micro Devices, Inc.
19 * All rights reserved.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100020 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000021 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions are met:
23 * * Redistributions of source code must retain the above copyright
24 * notice, this list of conditions and the following disclaimer.
25 * * Redistributions in binary form must reproduce the above copyright
26 * notice, this list of conditions and the following disclaimer in the
27 * documentation and/or other materials provided with the distribution.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100028 * * Neither the name of Advanced Micro Devices, Inc. nor the names of
29 * its contributors may be used to endorse or promote products derived
Frank Vibrans2b4c8312011-02-14 18:30:54 +000030 * from this software without specific prior written permission.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100031 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000032 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
34 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
35 * DISCLAIMED. IN NO EVENT SHALL ADVANCED MICRO DEVICES, INC. BE LIABLE FOR ANY
36 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
38 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
39 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
40 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
41 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Edward O'Callaghan1542a6f2014-07-06 19:24:06 +100042 *
Frank Vibrans2b4c8312011-02-14 18:30:54 +000043 * ***************************************************************************
44 *
45 */
46
47/*----------------------------------------------------------------------------------------
48 * M O D U L E S U S E D
49 *----------------------------------------------------------------------------------------
50 */
51#include "AGESA.h"
52#include "Ids.h"
53#include "amdlib.h"
54#include "Gnb.h"
55#include "GnbPcie.h"
56#include GNB_MODULE_DEFINITIONS (GnbCommonLib)
57#include GNB_MODULE_DEFINITIONS (GnbPcieConfig)
58#include GNB_MODULE_DEFINITIONS (GnbPcieInitLibV1)
59#include "GnbRegistersON.h"
60#include "Filecode.h"
61#define FILECODE PROC_GNB_MODULES_GNBPCIEINITLIBV1_PCIEUTILITYLIB_FILECODE
62/*----------------------------------------------------------------------------------------
63 * D E F I N I T I O N S A N D M A C R O S
64 *----------------------------------------------------------------------------------------
65 */
66
67
68/*----------------------------------------------------------------------------------------
69 * T Y P E D E F S A N D S T R U C T U R E S
70 *----------------------------------------------------------------------------------------
71 */
72typedef struct {
73 UINT32 Flags;
74 PCIE_LINK_SPEED_CAP LinkSpeedCapability;
75} PCIE_GLOBAL_GEN_CAP_WORKSPACE;
76
77/*----------------------------------------------------------------------------------------
78 * P R O T O T Y P E S O F L O C A L F U N C T I O N S
79 *----------------------------------------------------------------------------------------
80 */
81
82/*----------------------------------------------------------------------------------------*/
83/**
84 * Get link state history from HW state machine
85 *
86 *
87 *
88 * @param[in] Engine Pointer to engine config descriptor
89 * @param[out] History Buffer to save history
90 * @param[in] Length Buffer length
91 * @param[in] Pcie Pointer to global PCIe configuration
92 */
93
94VOID
95PcieUtilGetLinkHwStateHistory (
96 IN PCIe_ENGINE_CONFIG *Engine,
97 OUT UINT8 *History,
98 IN UINT8 Length,
99 IN PCIe_PLATFORM_CONFIG *Pcie
100 )
101{
102 UINT8 ReadLength;
103 UINT32 LocalHistory [6];
104 UINT16 Index;
105 ASSERT (Length <= 16);
106 ASSERT (Length > 0);
107 if (Length > 6*4) {
108 Length = 6*4;
109 }
110 ReadLength = (Length + 3) / 4;
111 for (Index = 0; Index < ReadLength; Index++) {
112 LocalHistory[Index] = PciePortRegisterRead (
113 Engine,
114 DxF0xE4_xA5_ADDRESS + Index,
115 Pcie
116 );
117 }
118 LibAmdMemCopy (History, LocalHistory, Length, GnbLibGetHeader (Pcie));
119}
120
121/*----------------------------------------------------------------------------------------*/
122/**
123 * Search array for specific pattern
124 *
125 *
126 * @param[in] Buf1 Pointer to source buffer which will be subject of search
127 * @param[in] Buf1Length Length of the source buffer
128 * @param[in] Buf2 Pointer to pattern buffer
129 * @param[in] Buf2Length Length of the pattern buffer
130 * @retval TRUE Pattern found
131 * @retval TRUE Pattern not found
132 */
133
134BOOLEAN
135PcieUtilSearchArray (
136 IN UINT8 *Buf1,
137 IN UINTN Buf1Length,
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200138 CONST IN UINT8 *Buf2,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000139 IN UINTN Buf2Length
140 )
141{
142 UINT8 *CurrentBuf1Ptr;
143 CurrentBuf1Ptr = Buf1;
144 while (CurrentBuf1Ptr < (Buf1 + Buf1Length - Buf2Length)) {
145 UINT8 *SourceBufPtr;
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200146 CONST UINT8 *PatternBufPtr;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000147 UINTN PatternBufLength;
148 SourceBufPtr = CurrentBuf1Ptr;
149 PatternBufPtr = Buf2;
150 PatternBufLength = Buf2Length;
151 while ((*SourceBufPtr++ == *PatternBufPtr++) && (PatternBufLength-- != 0));
152 if (PatternBufLength == 0) {
153 return TRUE;
154 }
155 CurrentBuf1Ptr++;
156 }
157 return FALSE;
158}
159
160
161/*----------------------------------------------------------------------------------------*/
162/**
163 * Check if link reversed
164 *
165 *
166 * @param[in] HwLinkState Check for HW auto link reversal
167 * @param[in] Engine Pointer to engine config descriptor
168 * @param[in] Pcie Pointer to PCIe config descriptor
169 * @retval TRUE if link reversed
170 */
171BOOLEAN
172PcieUtilIsLinkReversed (
173 IN BOOLEAN HwLinkState,
174 IN PCIe_ENGINE_CONFIG *Engine,
175 IN PCIe_PLATFORM_CONFIG *Pcie
176 )
177{
178 UINT32 LinkReversal;
179
180 LinkReversal = (Engine->EngineData.StartLane > Engine->EngineData.EndLane) ? 1 : 0;
181 if (HwLinkState) {
182 DxF0xE4_x50_STRUCT DxF0xE4_x50;
183 DxF0xE4_x50.Value = PciePortRegisterRead (
184 Engine,
185 DxF0xE4_x50_ADDRESS,
186 Pcie
187 );
188 LinkReversal ^= DxF0xE4_x50.Field.PortLaneReversal;
189 }
190 return ((LinkReversal & BIT0) != 0) ? TRUE : FALSE;
191}
192
193
194/*----------------------------------------------------------------------------------------*/
195/**
196 * Get link width detected during training
197 *
198 *
199 *
200 * @param[in] Engine Pointer to engine config descriptor
201 * @param[in] Pcie Pointer to global PCIe configuration
202 * @retval Link width
203 */
204UINT8
205PcieUtilGetLinkWidth (
206 IN PCIe_ENGINE_CONFIG *Engine,
207 IN PCIe_PLATFORM_CONFIG *Pcie
208 )
209{
210 UINT8 LinkWidth;
211 DxF0xE4_xA2_STRUCT DxF0xE4_xA2;
212 DxF0xE4_xA2.Value = PciePortRegisterRead (
213 Engine,
214 DxF0xE4_xA2_ADDRESS,
215 Pcie
216 );
217 switch (DxF0xE4_xA2.Field.LcLinkWidthRd) {
218 case 0x6:
219 LinkWidth = 16;
220 break;
221 case 0x5:
222 LinkWidth = 12;
223 break;
224 case 0x4:
225 LinkWidth = 8;
226 break;
227 case 0x3:
228 LinkWidth = 4;
229 break;
230 case 0x2:
231 LinkWidth = 2;
232 break;
233 case 0x1:
234 LinkWidth = 1;
235 break;
236 default:
237 LinkWidth = 0;
238 }
239 return LinkWidth;
240}
241
242/*----------------------------------------------------------------------------------------*/
243/**
244 * Get bitmap of engine lane of requested type
245 *
246 *
247 * @param[in] IncludeLaneType Include Lane type
248 * @param[in] ExcludeLaneType Exclude Lane type
249 * @param[in] Engine Pointer to engine config descriptor
250 * @param[in] Pcie Pointer to global PCIe configuration
251 * @retval Lane bitmap
252 */
253
254UINT32
255PcieUtilGetEngineLaneBitMap (
256 IN UINT32 IncludeLaneType,
257 IN UINT32 ExcludeLaneType,
258 IN PCIe_ENGINE_CONFIG *Engine,
259 IN PCIe_PLATFORM_CONFIG *Pcie
260 )
261{
262 UINT32 LaneBitmap;
263 UINT16 LaneOffset;
264 LaneBitmap = 0;
265 if ((IncludeLaneType & LANE_TYPE_PCIE_LANES) && Engine->EngineData.EngineType == PciePortEngine) {
266 if (IncludeLaneType & LANE_TYPE_PCIE_ALL) {
267 LaneBitmap |= (((1 << PcieConfigGetNumberOfCoreLane (Engine)) - 1) << Engine->Type.Port.StartCoreLane);
268 }
269 if (PcieLibIsEngineAllocated (Engine)) {
270 if (IncludeLaneType & LANE_TYPE_PCIE_ALLOCATED) {
271 LaneBitmap |= (((1 << PcieConfigGetNumberOfPhyLane (Engine)) - 1) << Engine->Type.Port.StartCoreLane);
272 }
273 if (IncludeLaneType & LANE_TYPE_PCIE_ACTIVE) {
274 if (Engine->Type.Port.PortData.LinkHotplug == HotplugEnhanced) {
275 LaneBitmap |= PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_ALLOCATED, 0, Engine, Pcie);
276 } else if (PcieConfigCheckPortStatus (Engine, INIT_STATUS_PCIE_PORT_IN_COMPLIANCE)) {
277 LaneBitmap |= PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_ALLOCATED, 0, Engine, Pcie);
278 } else if (PcieConfigCheckPortStatus (Engine, INIT_STATUS_PCIE_TRAINING_SUCCESS)) {
279 UINT8 LinkWidth;
280 BOOLEAN LinkReversed;
281 LinkWidth = PcieUtilGetLinkWidth (Engine, Pcie);
282 if (LinkWidth > PcieConfigGetNumberOfPhyLane (Engine)) {
283 LinkWidth = PcieConfigGetNumberOfPhyLane (Engine);
284 }
285 LinkReversed = PcieUtilIsLinkReversed (TRUE, Engine, Pcie);
286 LaneOffset = LinkReversed ? (Engine->Type.Port.EndCoreLane - LinkWidth + 1) : Engine->Type.Port.StartCoreLane;
287 LaneBitmap |= (((1 << LinkWidth) - 1) << LaneOffset);
288 }
289 }
290 if (IncludeLaneType & LANE_TYPE_PCIE_SB) {
291 if (Engine->Type.Port.IsSB) {
292 LaneBitmap |= PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_ACTIVE, 0, Engine, Pcie);
293 IDS_HDT_CONSOLE (GNB_TRACE, "SB Lane Bitmap is 0x%x\n", LaneBitmap);
294 }
295 }
296 if (IncludeLaneType & LANE_TYPE_PCIE_HOTPLUG) {
297 if (Engine->Type.Port.PortData.LinkHotplug != HotplugDisabled) {
298 LaneBitmap |= PcieUtilGetEngineLaneBitMap (LANE_TYPE_PCIE_ALLOCATED, 0, Engine, Pcie);
299 }
300 }
301 }
302 }
303 if ((IncludeLaneType & LANE_TYPE_DDI_LANES) && Engine->EngineData.EngineType == PcieDdiEngine) {
304 if (PcieLibIsEngineAllocated (Engine)) {
305 if (IncludeLaneType & (LANE_TYPE_DDI_ALLOCATED | LANE_TYPE_DDI_ALL)) {
efdesign9884cbce22011-08-04 12:09:17 -0600306 LaneOffset = PcieLibGetLoPhyLane (Engine) - PcieEngineGetParentWrapper (Engine)->StartPhyLane;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000307 LaneBitmap |= ((1 << PcieConfigGetNumberOfPhyLane (Engine)) - 1) << LaneOffset;
308 }
309 if (IncludeLaneType & LANE_TYPE_DDI_ACTIVE) {
310 if (Engine->InitStatus & INIT_STATUS_DDI_ACTIVE) {
311 LaneBitmap |= PcieUtilGetEngineLaneBitMap (LANE_TYPE_DDI_ALL, 0, Engine, Pcie);
312 }
313 }
314 }
315 }
316 if (ExcludeLaneType != 0) {
317 LaneBitmap &= (~PcieUtilGetEngineLaneBitMap (ExcludeLaneType, 0, Engine, Pcie));
318 }
319 return LaneBitmap;
320}
321
322/*----------------------------------------------------------------------------------------*/
323/**
324 * Get bitmap of Wrapper lane of requested type
325 *
326 *
327 * @param[in] IncludeLaneType Include Lane type
328 * @param[in] ExcludeLaneType Exclude Lane type
329 * @param[in] Wrapper Pointer to wrapper config descriptor
330 * @param[in] Pcie Pointer to PCIe config descriptor
331 * @retval Lane bitmap
332 */
333
334UINT32
335PcieUtilGetWrapperLaneBitMap (
336 IN UINT32 IncludeLaneType,
337 IN UINT32 ExcludeLaneType,
338 IN PCIe_WRAPPER_CONFIG *Wrapper,
339 IN PCIe_PLATFORM_CONFIG *Pcie
340 )
341{
342 PCIe_ENGINE_CONFIG *EngineList;
343 UINT32 LaneBitmap;
344 EngineList = PcieWrapperGetEngineList (Wrapper);
345 LaneBitmap = 0;
346 if ((IncludeLaneType | ExcludeLaneType) != 0) {
347 if ((IncludeLaneType & LANE_TYPE_ALL) == LANE_TYPE_ALL) {
348 LaneBitmap = (1 << (Wrapper->EndPhyLane - Wrapper->StartPhyLane + 1)) - 1;
349 if (ExcludeLaneType != 0) {
350 LaneBitmap &= (~PcieUtilGetWrapperLaneBitMap (ExcludeLaneType, 0, Wrapper, Pcie));
351 }
352 } else {
353 while (EngineList != NULL) {
354 LaneBitmap |= PcieUtilGetEngineLaneBitMap (IncludeLaneType, ExcludeLaneType, EngineList, Pcie);
355 EngineList = PcieLibGetNextDescriptor (EngineList);
356 }
357 }
358 }
359 return LaneBitmap;
360}
361
362/*----------------------------------------------------------------------------------------*/
363/**
364 * Program port register table
365 *
366 *
367 *
368 * @param[in] Table Pointer to table
369 * @param[in] Length number of entries
370 * @param[in] Engine Pointer to engine config descriptor
371 * @param[in] S3Save Save for S3 flag
372 * @param[in] Pcie Pointer to global PCIe configuration
373 *
374 */
375
376VOID
377PciePortProgramRegisterTable (
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200378 CONST IN PCIE_PORT_REGISTER_ENTRY *Table,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000379 IN UINTN Length,
380 IN PCIe_ENGINE_CONFIG *Engine,
381 IN BOOLEAN S3Save,
382 IN PCIe_PLATFORM_CONFIG *Pcie
383 )
384{
385 UINTN Index;
386 UINT32 Value;
387 for (Index = 0; Index < Length; Index++) {
388 Value = PciePortRegisterRead (
389 Engine,
390 Table[Index].Reg,
391 Pcie
392 );
393 Value &= (~Table[Index].Mask);
394 Value |= Table[Index].Data;
395 PciePortRegisterWrite (
396 Engine,
397 Table[Index].Reg,
398 Value,
399 S3Save,
400 Pcie
401 );
402 }
403}
404
405
406/*----------------------------------------------------------------------------------------*/
407/**
408 * Lock registers
409 *
410 *
411 * @param[in] Wrapper Pointer to wrapper config descriptor
412 * @param[in] Pcie Pointer to global PCIe configuration
413 */
414
415VOID
416PcieLockRegisters (
417 IN PCIe_WRAPPER_CONFIG *Wrapper,
418 IN PCIe_PLATFORM_CONFIG *Pcie
419 )
420{
421 UINT8 CoreId;
422 IDS_HDT_CONSOLE (GNB_TRACE, "PcieLockRegisters Enter\n");
423 if (PcieLibIsPcieWrapper (Wrapper)) {
424 for (CoreId = Wrapper->StartPcieCoreId; CoreId <= Wrapper->EndPcieCoreId; CoreId++) {
425 PcieRegisterWriteField (
426 Wrapper,
Frank.Vibrans9c2fb602011-03-17 22:19:45 +0000427 CORE_SPACE (CoreId, 0x10),
428 0,
429 1,
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000430 0x1,
431 TRUE,
432 Pcie
433 );
434 }
435 }
436 IDS_HDT_CONSOLE (GNB_TRACE, "PcieLockRegisters Exit\n");
437}