blob: 26d33b1ab1e9e15b96626b14875c9cf3d18f9309 [file] [log] [blame]
Frank Vibrans2b4c8312011-02-14 18:30:54 +00001/* $NoKeywords:$ */
2/**
3 * @file
4 *
5 * PCIe link training
6 *
7 *
8 *
9 * @xrefitem bom "File Content Label" "Release Content"
10 * @e project: AGESA
11 * @e sub-project: GNB
12 * @e \$Revision: 38950 $ @e \$Date: 2010-10-03 23:49:09 -0700 (Sun, 03 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 "GeneralServices.h"
55#include "Gnb.h"
56#include "GnbPcie.h"
57#include GNB_MODULE_DEFINITIONS (GnbCommonLib)
58#include GNB_MODULE_DEFINITIONS (GnbPcieConfig)
59#include GNB_MODULE_DEFINITIONS (GnbPcieInitLibV1)
60#include "PcieWorkarounds.h"
efdesign9884cbce22011-08-04 12:09:17 -060061#include "PcieTraining.h"
Frank Vibrans2b4c8312011-02-14 18:30:54 +000062#include "GnbRegistersON.h"
63#include "Filecode.h"
64#define FILECODE PROC_GNB_MODULES_GNBPCIETRAININGV1_PCIETRAINING_FILECODE
65/*----------------------------------------------------------------------------------------
66 * D E F I N I T I O N S A N D M A C R O S
67 *----------------------------------------------------------------------------------------
68 */
69
70
71/*----------------------------------------------------------------------------------------
72 * T Y P E D E F S A N D S T R U C T U R E S
73 *----------------------------------------------------------------------------------------
74 */
75
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 */
efdesign9884cbce22011-08-04 12:09:17 -060081VOID
82PcieSetResetStateOnEngines (
83 IN PCIe_ENGINE_CONFIG *Engine,
84 IN OUT VOID *Buffer,
85 IN PCIe_PLATFORM_CONFIG *Pcie
86 );
Frank Vibrans2b4c8312011-02-14 18:30:54 +000087
88VOID
efdesign9884cbce22011-08-04 12:09:17 -060089PcieTrainingCheckResetDuration (
Frank Vibrans2b4c8312011-02-14 18:30:54 +000090 IN PCIe_ENGINE_CONFIG *CurrentEngine,
91 IN PCIe_PLATFORM_CONFIG *Pcie
92 );
93
efdesign9884cbce22011-08-04 12:09:17 -060094VOID
95PcieTrainingDeassertReset (
96 IN PCIe_ENGINE_CONFIG *CurrentEngine,
97 IN PCIe_PLATFORM_CONFIG *Pcie
98 );
99
100VOID
101PcieTrainingBrokenLine (
102 IN PCIe_ENGINE_CONFIG *CurrentEngine,
103 IN PCIe_PLATFORM_CONFIG *Pcie
104 );
105
106VOID
107PcieTrainingGen2Fail (
108 IN PCIe_ENGINE_CONFIG *CurrentEngine,
109 IN PCIe_PLATFORM_CONFIG *Pcie
110 );
111
112GNB_DEBUG_CODE (
113 VOID
114 STATIC
115 PcieTrainingDebugDumpPortState (
116 IN PCIe_ENGINE_CONFIG *CurrentEngine,
117 IN PCIe_PLATFORM_CONFIG *Pcie
118 );
119)
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000120
121/*----------------------------------------------------------------------------------------*/
122/**
123 * Set link State
124 *
125 *
126 * @param[in] CurrentEngine Pointer to engine config descriptor
127 * @param[in] State State to set
128 * @param[in] UpdateTimeStamp Update time stamp
129 * @param[in] Pcie Pointer to global PCIe configuration
130 *
131 */
132VOID
133PcieTrainingSetPortState (
134 IN PCIe_ENGINE_CONFIG *CurrentEngine,
135 IN UINT8 State,
136 IN BOOLEAN UpdateTimeStamp,
137 IN PCIe_PLATFORM_CONFIG *Pcie
138 )
139{
140 UINT32 TimeStamp;
141 CurrentEngine->Type.Port.State = State;
142 if (UpdateTimeStamp) {
143 TimeStamp = PcieTimerGetTimeStamp (Pcie);
144 CurrentEngine->Type.Port.TimeStamp = TimeStamp;
145 }
146 GNB_DEBUG_CODE (
147 PcieTrainingDebugDumpPortState (CurrentEngine, Pcie)
148 );
efdesign9884cbce22011-08-04 12:09:17 -0600149
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000150}
151
152
153/*----------------------------------------------------------------------------------------*/
154/**
155 * Set state for all engines connected to same reset ID
156 *
157 *
158 *
159 * @param[in] Engine Pointer to engine config descriptor
160 * @param[in, out] Buffer Pointer to Reset Id
161 * @param[in] Pcie Pointer to global PCIe configuration
162 *
163 */
164VOID
165PcieSetResetStateOnEngines (
166 IN PCIe_ENGINE_CONFIG *Engine,
167 IN OUT VOID *Buffer,
168 IN PCIe_PLATFORM_CONFIG *Pcie
169 )
170{
171 UINT8 ResetId;
172 ResetId = *(UINT8 *)Buffer;
173 if (Engine->Type.Port.PortData.ResetId == ResetId) {
174 PcieTrainingSetPortState (Engine, LinkStateResetDuration, TRUE, Pcie);
175 }
176}
177
178
179/*----------------------------------------------------------------------------------------*/
180/**
181 * Assert GPIO port reset.
182 *
183 * Transition to LinkStateResetDuration state
184 *
185 * @param[in] CurrentEngine Pointer to engine config descriptor
186 * @param[in] Pcie Pointer to global PCIe configuration
187 *
188 */
189VOID
190STATIC
191PcieTrainingAssertReset (
192 IN PCIe_ENGINE_CONFIG *CurrentEngine,
193 IN PCIe_PLATFORM_CONFIG *Pcie
194 )
195{
196 PCIe_SLOT_RESET_INFO ResetInfo;
197 ResetInfo.ResetControl = AssertSlotReset;
198 ResetInfo.ResetId = CurrentEngine->Type.Port.PortData.ResetId;
199 LibAmdMemCopy (&ResetInfo.StdHeader, GnbLibGetHeader (Pcie), sizeof (AMD_CONFIG_PARAMS), GnbLibGetHeader (Pcie));
200 AgesaPcieSlotResetControl (0, &ResetInfo);
201 PcieConfigRunProcForAllEngines (
202 DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE,
203 PcieSetResetStateOnEngines,
204 (VOID *)&CurrentEngine->Type.Port.PortData.ResetId,
205 Pcie
206 );
207}
208
209
210/*----------------------------------------------------------------------------------------*/
211/**
212 * Check for reset duration
213 *
214 * Transition to LinkStateResetDuration state
215 *
216 * @param[in] CurrentEngine Pointer to engine config descriptor
217 * @param[in] Pcie Pointer to global PCIe configuration
218 *
219 */
220VOID
221PcieTrainingCheckResetDuration (
222 IN PCIe_ENGINE_CONFIG *CurrentEngine,
223 IN PCIe_PLATFORM_CONFIG *Pcie
224 )
225{
226 UINT32 TimeStamp;
227 TimeStamp = PcieTimerGetTimeStamp (Pcie);
228 if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkGpioResetAssertionTime) {
229 PcieTrainingSetPortState (CurrentEngine, LinkStateResetExit, FALSE, Pcie);
230 }
231}
232
233/*----------------------------------------------------------------------------------------*/
234/**
235 * Deassert GPIO port reset.
236 *
237 * Transition to LinkStateResetDuration state
238 *
239 * @param[in] CurrentEngine Pointer to engine config descriptor
240 * @param[in] Pcie Platform configuration
241 *
242 */
243VOID
244PcieTrainingDeassertReset (
245 IN PCIe_ENGINE_CONFIG *CurrentEngine,
246 IN PCIe_PLATFORM_CONFIG *Pcie
247 )
248{
249 PCIe_SLOT_RESET_INFO ResetInfo;
250 ResetInfo.ResetControl = DeassertSlotReset;
251 ResetInfo.ResetId = CurrentEngine->Type.Port.PortData.ResetId;
252 LibAmdMemCopy (&ResetInfo.StdHeader, GnbLibGetHeader (Pcie), sizeof (AMD_CONFIG_PARAMS), GnbLibGetHeader (Pcie));
253 AgesaPcieSlotResetControl (0, &ResetInfo);
254 PcieTrainingSetPortState (CurrentEngine, LinkTrainingResetTimeout, TRUE, Pcie);
255}
256
257/*----------------------------------------------------------------------------------------*/
258/**
259 * Check for after reset deassertion timeout
260 *
261 *
262 * @param[in] CurrentEngine Pointer to engine config descriptor
263 * @param[in] Pcie Pointer to global PCIe configuration
264 *
265 */
266VOID
267STATIC
268PcieTrainingCheckResetTimeout (
269 IN PCIe_ENGINE_CONFIG *CurrentEngine,
270 IN PCIe_PLATFORM_CONFIG *Pcie
271 )
272{
273 UINT32 TimeStamp;
274 TimeStamp = PcieTimerGetTimeStamp (Pcie);
275 if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkResetToTrainingTime) {
276 PcieTrainingSetPortState (CurrentEngine, LinkStateReleaseTraining, FALSE, Pcie);
277 }
278}
279
280
281/*----------------------------------------------------------------------------------------*/
282/**
283 * Release training
284 *
285 *
286 * @param[in] CurrentEngine Pointer to engine config descriptor
287 * @param[in] Pcie Pointer to global PCIe configuration
288 *
289 */
290VOID
291STATIC
292PcieTrainingRelease (
293 IN PCIe_ENGINE_CONFIG *CurrentEngine,
294 IN PCIe_PLATFORM_CONFIG *Pcie
295 )
296{
297 UINT8 LinkTrainingState;
298 PcieRegisterWriteField (
299 PcieEngineGetParentWrapper (CurrentEngine),
300 WRAP_SPACE (PcieEngineGetParentWrapper (CurrentEngine)->WrapId, D0F0xE4_WRAP_0800_ADDRESS + 0x100 * CurrentEngine->Type.Port.PortId),
301 D0F0xE4_WRAP_0800_HoldTraining_OFFSET,
302 D0F0xE4_WRAP_0800_HoldTraining_WIDTH,
303 0,
304 FALSE,
305 Pcie
306 );
307 if (CurrentEngine->Type.Port.PortData.MiscControls.LinkComplianceMode == 0x1) {
308 LinkTrainingState = LinkStateCompliance;
309 } else {
310 LinkTrainingState = LinkStateDetectPresence;
311 }
312 PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, TRUE, Pcie);
313}
314
315/*----------------------------------------------------------------------------------------*/
316/**
317 * Detect presence of any EP on the link
318 *
319 *
320 * @param[in] CurrentEngine Pointer to engine config descriptor
321 * @param[in] Pcie Pointer to global PCIe configuration
322 *
323 */
324
325VOID
326STATIC
327PcieTrainingDetectPresence (
328 IN PCIe_ENGINE_CONFIG *CurrentEngine,
329 IN PCIe_PLATFORM_CONFIG *Pcie
330 )
331{
332 UINT8 LinkHwStateHistory[4];
333 UINT32 TimeStamp;
334 PcieUtilGetLinkHwStateHistory (CurrentEngine, &LinkHwStateHistory[0], 4, Pcie);
335 if (LinkHwStateHistory[0] > 4) {
336 PcieTrainingSetPortState (CurrentEngine, LinkStateDetecting, TRUE, Pcie);
337 return;
338 }
339 TimeStamp = PcieTimerGetTimeStamp (Pcie);
340 if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkReceiverDetectionPooling) {
341 PcieTrainingSetPortState (CurrentEngine, LinkStateDeviceNotPresent, FALSE, Pcie);
342 }
343}
344
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200345CONST UINT8 FailPattern1 [] = {0x2a, 0x6};
346CONST UINT8 FailPattern2 [] = {0x2a, 0x9};
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000347
348/*----------------------------------------------------------------------------------------*/
349/**
350 * Detect Link State
351 *
352 *
353 * @param[in] CurrentEngine Pointer to engine config descriptor
354 * @param[in] Pcie Pointer to global PCIe configuration
355 *
356 */
357
358VOID
359STATIC
360PcieTrainingDetectLinkState (
361 IN PCIe_ENGINE_CONFIG *CurrentEngine,
362 IN PCIe_PLATFORM_CONFIG *Pcie
363 )
364{
365 UINT8 LinkHwStateHistory[16];
366 UINT32 TimeStamp;
367 UINT8 LinkTrainingState;
368 PcieUtilGetLinkHwStateHistory (CurrentEngine, &LinkHwStateHistory[0], 4, Pcie);
369 if (LinkHwStateHistory[0] == 0x10) {
370 PcieTrainingSetPortState (CurrentEngine, LinkStateL0, FALSE, Pcie);
371 return;
372 };
373 TimeStamp = PcieTimerGetTimeStamp (Pcie);
374 if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= Pcie->LinkL0Pooling) {
375 LinkTrainingState = LinkStateTrainingFail;
376 PcieUtilGetLinkHwStateHistory (CurrentEngine, &LinkHwStateHistory[0], 16, Pcie);
377 if (LinkHwStateHistory[0] == 0x7) {
378 LinkTrainingState = LinkStateCompliance;
379 } else if (PcieUtilSearchArray (LinkHwStateHistory, sizeof (LinkHwStateHistory), FailPattern1, sizeof (FailPattern1))) {
380 LinkTrainingState = LinkStateBrokenLane;
381 } else if (PcieUtilSearchArray (LinkHwStateHistory, sizeof (LinkHwStateHistory), FailPattern2, sizeof (FailPattern2))) {
382 LinkTrainingState = LinkStateGen2Fail;
383 }
384 PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, FALSE, Pcie);
385 }
386}
387
388/*----------------------------------------------------------------------------------------*/
389/**
390 * Broken Lane
391 *
392 *
393 * @param[in] CurrentEngine Pointer to engine config descriptor
394 * @param[in] Pcie Pointer to global PCIe configuration
395 *
396 */
397
398VOID
399PcieTrainingBrokenLine (
400 IN PCIe_ENGINE_CONFIG *CurrentEngine,
401 IN PCIe_PLATFORM_CONFIG *Pcie
402 )
403{
404 UINT8 CurrentLinkWidth;
405 UINT8 LinkTrainingState;
406 CurrentLinkWidth = PcieUtilGetLinkWidth (CurrentEngine, Pcie);
407 if (CurrentLinkWidth < PcieConfigGetNumberOfPhyLane (CurrentEngine) && CurrentLinkWidth > 0) {
efdesign9884cbce22011-08-04 12:09:17 -0600408 CurrentEngine->InitStatus |= INIT_STATUS_PCIE_PORT_BROKEN_LANE_RECOVERY;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000409 PcieTopologyReduceLinkWidth (CurrentLinkWidth, CurrentEngine, Pcie);
410 LinkTrainingState = LinkStateResetAssert;
411 PutEventLog (
412 AGESA_WARNING,
413 GNB_EVENT_BROKEN_LANE_RECOVERY,
414 CurrentEngine->Type.Port.Address.AddressValue,
415 0,
416 0,
417 0,
418 GnbLibGetHeader (Pcie)
419 );
420 } else {
421 LinkTrainingState = LinkStateGen2Fail;
422 }
423 PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, FALSE, Pcie);
424}
425
426/*----------------------------------------------------------------------------------------*/
427/**
428 * Check if link fail because device does not support Gen2
429 *
430 *
431 * @param[in] CurrentEngine Pointer to engine config descriptor
432 * @param[in] Pcie Pointer to global PCIe configuration
433 *
434 */
435VOID
436PcieTrainingGen2Fail (
437 IN PCIe_ENGINE_CONFIG *CurrentEngine,
438 IN PCIe_PLATFORM_CONFIG *Pcie
439 )
440{
441 UINT8 LinkTrainingState;
442 if (CurrentEngine->Type.Port.PortData.MiscControls.LinkSafeMode != PcieGen1) {
443 PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_PORT_GEN2_RECOVERY, 0);
444 CurrentEngine->Type.Port.PortData.MiscControls.LinkSafeMode = PcieGen1;
445 PcieLinkSafeMode (CurrentEngine, Pcie);
446 LinkTrainingState = LinkStateResetAssert;
447 PutEventLog (
448 AGESA_WARNING,
449 GNB_EVENT_BROKEN_LANE_RECOVERY,
450 CurrentEngine->Type.Port.Address.AddressValue,
451 0,
452 0,
453 0,
454 GnbLibGetHeader (Pcie)
455 );
456 } else {
457 LinkTrainingState = LinkStateTrainingFail;
458 }
459 PcieTrainingSetPortState (CurrentEngine, LinkTrainingState, FALSE, Pcie);
460}
461
462/*----------------------------------------------------------------------------------------*/
463/**
464 * Link in L0
465 *
466 *
467 * @param[in] CurrentEngine Pointer to engine config descriptor
468 * @param[in] Pcie Pointer to global PCIe configuration
469 *
470 */
471VOID
472STATIC
473PcieCheckLinkL0 (
474 IN PCIe_ENGINE_CONFIG *CurrentEngine,
475 IN PCIe_PLATFORM_CONFIG *Pcie
476 )
477{
478 PcieTrainingSetPortState (CurrentEngine, LinkStateVcoNegotiation, TRUE, Pcie);
479}
480/*----------------------------------------------------------------------------------------*/
481/**
482 * Check if link fail because device does not support Gen X
483 *
484 *
485 * @param[in] CurrentEngine Pointer to engine config descriptor
486 * @param[in] Pcie Pointer to global PCIe configuration
487 *
488 */
489VOID
490STATIC
491PcieTrainingCheckVcoNegotiation (
492 IN PCIe_ENGINE_CONFIG *CurrentEngine,
493 IN PCIe_PLATFORM_CONFIG *Pcie
494 )
495{
496 UINT32 TimeStamp;
497 DxF0x128_STRUCT DxF0x128;
498 TimeStamp = PcieTimerGetTimeStamp (Pcie);
499 GnbLibPciRead (CurrentEngine->Type.Port.Address.AddressValue | DxF0x128_ADDRESS, AccessWidth32, &DxF0x128, GnbLibGetHeader (Pcie));
500 if (DxF0x128.Field.VcNegotiationPending == 0) {
501 UINT16 NumberOfPhyLane;
502 NumberOfPhyLane = PcieConfigGetNumberOfPhyLane (CurrentEngine);
503 if (Pcie->GfxCardWorkaround == GfxWorkaroundEnable && NumberOfPhyLane >= 8) {
504 // Limit exposure of workaround to x8 and x16 port.
505 PcieTrainingSetPortState (CurrentEngine, LinkStateGfxWorkaround, TRUE, Pcie);
506 } else {
507 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingSuccess, FALSE, Pcie);
508 }
509 return;
510 }
511 if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= 1000 * 1000) {
512 PcieTrainingSetPortState (CurrentEngine, LinkStateRetrain, FALSE, Pcie);
513 }
514}
515
516/*----------------------------------------------------------------------------------------*/
517/**
518 * Check if for GFX workaround condition
519 *
520 *
521 * @param[in] CurrentEngine Pointer to engine config descriptor
522 * @param[in] Pcie Pointer to global PCIe configuration
523 *
524 */
525VOID
526STATIC
527PcieTrainingGfxWorkaround (
528 IN PCIe_ENGINE_CONFIG *CurrentEngine,
529 IN PCIe_PLATFORM_CONFIG *Pcie
530 )
531{
532 UINT32 TimeStamp;
533 GFX_WORKAROUND_STATUS GfxWorkaroundStatus;
534 TimeStamp = PcieTimerGetTimeStamp (Pcie);
535
536 GfxWorkaroundStatus = PcieGfxCardWorkaround (CurrentEngine->Type.Port.Address, GnbLibGetHeader (Pcie));
537 switch (GfxWorkaroundStatus) {
538 case GFX_WORKAROUND_DEVICE_NOT_READY:
539 if (TIMESTAMPS_DELTA (TimeStamp, CurrentEngine->Type.Port.TimeStamp) >= 1000 * 2000) {
540 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingFail, TRUE, Pcie);
541 }
542 break;
543 case GFX_WORKAROUND_SUCCESS:
544 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingSuccess, FALSE, Pcie);
545 break;
546 case GFX_WORKAROUND_RESET_DEVICE:
547 if (CurrentEngine->Type.Port.GfxWrkRetryCount < 5) {
548 CurrentEngine->Type.Port.GfxWrkRetryCount++;
549 PcieTrainingSetPortState (CurrentEngine, LinkStateResetAssert, TRUE, Pcie);
550 } else {
551 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingFail, TRUE, Pcie);
552 }
553 break;
554 default:
555 ASSERT (FALSE);
556 }
557}
558
559/*----------------------------------------------------------------------------------------*/
560/**
561 * Retrain link
562 *
563 *
564 * @param[in] CurrentEngine Pointer to engine config descriptor
565 * @param[in] Pcie Pointer to global PCIe configuration
566 *
567 */
568VOID
569STATIC
570PcieTrainingRetrainLink (
571 IN PCIe_ENGINE_CONFIG *CurrentEngine,
572 IN PCIe_PLATFORM_CONFIG *Pcie
573 )
574{
575 PciePortRegisterWriteField (
576 CurrentEngine,
577 DxF0xE4_xA2_ADDRESS,
578 DxF0xE4_xA2_LcReconfigNow_OFFSET,
579 DxF0xE4_xA2_LcReconfigNow_WIDTH,
580 1,
581 FALSE,
582 Pcie
583 );
584 PcieTrainingSetPortState (CurrentEngine, LinkStateDetecting, TRUE, Pcie);
585}
586
587/*----------------------------------------------------------------------------------------*/
588/**
589 * Training fail on this port
590 *
591 *
592 * @param[in] CurrentEngine Pointer to engine config descriptor
593 * @param[in] Pcie Pointer to global PCIe configuration
594 *
595 */
596VOID
597STATIC
598PcieTrainingFail (
599 IN PCIe_ENGINE_CONFIG *CurrentEngine,
600 IN PCIe_PLATFORM_CONFIG *Pcie
601 )
602{
603 PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_PORT_TRAINING_FAIL, 0);
604 PcieTrainingSetPortState (CurrentEngine, LinkStateDeviceNotPresent, FALSE, Pcie);
605}
606
607/*----------------------------------------------------------------------------------------*/
608/**
609 * Links training success
610 *
611 *
612 * @param[in] CurrentEngine Pointer to engine config descriptor
613 * @param[in] Pcie Pointer to global PCIe configuration
614 *
615 */
616
617VOID
618STATIC
619PcieTrainingSuccess (
620 IN PCIe_ENGINE_CONFIG *CurrentEngine,
621 IN PCIe_PLATFORM_CONFIG *Pcie
622 )
623{
624 PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_TRAINING_SUCCESS, 0);
625 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingCompleted, FALSE, Pcie);
626}
627
628/*----------------------------------------------------------------------------------------*/
629/**
630 * Links in compliance
631 *
632 *
633 * @param[in] CurrentEngine Pointer to engine config descriptor
634 * @param[in] Pcie Pointer to global PCIe configuration
635 *
636 */
637VOID
638STATIC
639PcieTrainingCompliance (
640 IN PCIe_ENGINE_CONFIG *CurrentEngine,
641 IN PCIe_PLATFORM_CONFIG *Pcie
642 )
643{
644 PcieConfigUpdatePortStatus (CurrentEngine, INIT_STATUS_PCIE_PORT_IN_COMPLIANCE, 0);
645 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingCompleted, FALSE, Pcie);
646}
647
648/*----------------------------------------------------------------------------------------*/
649/**
650 * PCie EP not present
651 *
652 *
653 * @param[in] CurrentEngine Pointer to engine config descriptor
654 * @param[in] Pcie Pointer to global PCIe configuration
655 *
656 */
657VOID
658STATIC
659PcieTrainingNotPresent (
660 IN PCIe_ENGINE_CONFIG *CurrentEngine,
661 IN PCIe_PLATFORM_CONFIG *Pcie
662 )
663{
664 if ((CurrentEngine->Type.Port.PortData.LinkHotplug == HotplugEnhanced) || (CurrentEngine->Type.Port.PortData.LinkHotplug == HotplugServer)) {
665 } else {
666 PcieRegisterWriteField (
667 PcieEngineGetParentWrapper (CurrentEngine),
668 WRAP_SPACE (PcieEngineGetParentWrapper (CurrentEngine)->WrapId, D0F0xE4_WRAP_0800_ADDRESS + 0x100 * CurrentEngine->Type.Port.PortId),
669 D0F0xE4_WRAP_0800_HoldTraining_OFFSET,
670 D0F0xE4_WRAP_0800_HoldTraining_WIDTH,
671 1,
672 FALSE,
673 Pcie
674 );
675 }
676 PcieTrainingSetPortState (CurrentEngine, LinkStateTrainingCompleted, FALSE, Pcie);
677}
678
679/*----------------------------------------------------------------------------------------*/
680/**
681 * Final state. Port training completed.
682 *
683 * Initialization status recorded in PCIe_ENGINE_CONFIG.InitStatus
684 *
685 * @param[in] CurrentEngine Pointer to engine config descriptor
686 * @param[in] Pcie Pointer to global PCIe configuration
687 *
688 */
689VOID
690STATIC
691PcieTrainingCompleted (
692 IN PCIe_ENGINE_CONFIG *CurrentEngine,
693 IN PCIe_PLATFORM_CONFIG *Pcie
694 )
695{
696}
697
698/*----------------------------------------------------------------------------------------*/
699/**
700 * Training state handling
701 *
702 *
703 *
704 * @param[in] Engine Pointer to engine config descriptor
705 * @param[in, out] Buffer Indicate if engine in non final state
706 * @param[in] Pcie Pointer to global PCIe configuration
707 *
708 */
709
710VOID
711STATIC
712PcieTrainingPortCallback (
713 IN PCIe_ENGINE_CONFIG *Engine,
714 IN OUT VOID *Buffer,
715 IN PCIe_PLATFORM_CONFIG *Pcie
716 )
717{
718 BOOLEAN *TrainingComplete;
719 TrainingComplete = (BOOLEAN *) Buffer;
efdesign9884cbce22011-08-04 12:09:17 -0600720 if (Engine->Type.Port.State < Pcie->TrainingExitState) {
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000721 *TrainingComplete = FALSE;
efdesign9884cbce22011-08-04 12:09:17 -0600722 } else {
723 return;
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000724 }
725 switch (Engine->Type.Port.State) {
726 case LinkStateResetAssert:
727 PcieTrainingAssertReset (Engine, Pcie);
728 break;
729 case LinkStateResetDuration:
730 PcieTrainingCheckResetDuration (Engine, Pcie);
731 break;
732 case LinkStateResetExit:
733 PcieTrainingDeassertReset (Engine, Pcie);
734 break;
735 case LinkTrainingResetTimeout:
736 PcieTrainingCheckResetTimeout (Engine, Pcie);
737 break;
738 case LinkStateReleaseTraining:
739 PcieTrainingRelease (Engine, Pcie);
740 break;
741 case LinkStateDetectPresence:
742 PcieTrainingDetectPresence (Engine, Pcie);
743 break;
744 case LinkStateDetecting:
745 PcieTrainingDetectLinkState (Engine, Pcie);
746 break;
747 case LinkStateBrokenLane:
748 PcieTrainingBrokenLine (Engine, Pcie);
749 break;
750 case LinkStateGen2Fail:
751 PcieTrainingGen2Fail (Engine, Pcie);
752 break;
753 case LinkStateL0:
754 PcieCheckLinkL0 (Engine, Pcie);
755 break;
756 case LinkStateVcoNegotiation:
757 PcieTrainingCheckVcoNegotiation (Engine, Pcie);
758 break;
759 case LinkStateRetrain:
760 PcieTrainingRetrainLink (Engine, Pcie);
761 break;
762 case LinkStateTrainingFail:
763 PcieTrainingFail (Engine, Pcie);
764 break;
765 case LinkStateGfxWorkaround:
766 PcieTrainingGfxWorkaround (Engine, Pcie);
767 break;
768 case LinkStateTrainingSuccess:
769 PcieTrainingSuccess (Engine, Pcie);
770 break;
771 case LinkStateCompliance:
772 PcieTrainingCompliance (Engine, Pcie);
773 break;
774 case LinkStateDeviceNotPresent:
775 PcieTrainingNotPresent (Engine, Pcie);
776 break;
777 case LinkStateTrainingCompleted:
778 PcieTrainingCompleted (Engine, Pcie);
779 break;
780 default:
781 break;
782 }
783
784}
785
786
787/*----------------------------------------------------------------------------------------*/
788/**
789 * Main link training procedure
790 *
791 * Port end up in three possible state LinkStateTrainingNotPresent/LinkStateCompliance/
792 * LinkStateTrainingSuccess
793 *
794 * @param[in] Pcie Pointer to global PCIe configuration
795 * @retval AGESA_STATUS
796 *
797 */
798
799AGESA_STATUS
800PcieTraining (
801 IN PCIe_PLATFORM_CONFIG *Pcie
802 )
803{
804 AGESA_STATUS Status;
805 BOOLEAN TrainingComplete;
806 Status = AGESA_SUCCESS;
807 IDS_HDT_CONSOLE (GNB_TRACE, "PcieTraining Enter\n");
808 do {
809 TrainingComplete = TRUE;
810 PcieConfigRunProcForAllEngines (
811 DESCRIPTOR_ALLOCATED | DESCRIPTOR_PCIE_ENGINE,
812 PcieTrainingPortCallback,
813 &TrainingComplete,
814 Pcie
815 );
816 } while (!TrainingComplete);
817 IDS_HDT_CONSOLE (GNB_TRACE, "PcieTraining Exit [%x]\n", Status);
818 return Status;
819}
820
821/*----------------------------------------------------------------------------------------*/
822/**
823 * Helper function to dump port state on state transition
824 *
825 *
826 * @param[in] CurrentEngine Pointer to engine config descriptor
827 * @param[in] Pcie Pointer to global PCIe configuration
828 *
829 */
830
efdesign9884cbce22011-08-04 12:09:17 -0600831GNB_DEBUG_CODE (
Frank Vibrans2b4c8312011-02-14 18:30:54 +0000832VOID
833STATIC
834PcieTrainingDebugDumpPortState (
835 IN PCIe_ENGINE_CONFIG *CurrentEngine,
836 IN PCIe_PLATFORM_CONFIG *Pcie
837 )
838{
839 IDS_HDT_CONSOLE (PCIE_MISC, " Port %d:%d:%d State [%s] Time Stamp [%d]\n",
840 CurrentEngine->Type.Port.Address.Address.Bus,
841 CurrentEngine->Type.Port.Address.Address.Device,
842 CurrentEngine->Type.Port.Address.Address.Function,
843 (CurrentEngine->Type.Port.State == LinkStateTrainingFail) ? "LinkStateTrainingFail " : (
844 (CurrentEngine->Type.Port.State == LinkStateTrainingSuccess) ? "LinkStateTrainingSuccess " : (
845 (CurrentEngine->Type.Port.State == LinkStateCompliance) ? "LinkStateCompliance " : (
846 (CurrentEngine->Type.Port.State == LinkStateDeviceNotPresent) ? "LinkStateDeviceNotPresent" : (
847 (CurrentEngine->Type.Port.State == LinkStateResetAssert) ? "LinkStateResetAssert " : (
848 (CurrentEngine->Type.Port.State == LinkStateResetDuration) ? "LinkStateResetDuration " : (
849 (CurrentEngine->Type.Port.State == LinkStateResetDuration) ? "LinkStateResetExit " : (
850 (CurrentEngine->Type.Port.State == LinkTrainingResetTimeout) ? "LinkTrainingResetTimeout " : (
851 (CurrentEngine->Type.Port.State == LinkStateReleaseTraining) ? "LinkStateReleaseTraining " : (
852 (CurrentEngine->Type.Port.State == LinkStateDetectPresence) ? "LinkStateDetectPresence " : (
853 (CurrentEngine->Type.Port.State == LinkStateDetecting) ? "LinkStateDetecting " : (
854 (CurrentEngine->Type.Port.State == LinkStateBrokenLane) ? "LinkStateBrokenLane " : (
855 (CurrentEngine->Type.Port.State == LinkStateGen2Fail) ? "LinkStateGen2Fail " : (
856 (CurrentEngine->Type.Port.State == LinkStateL0) ? "LinkStateL0 " : (
857 (CurrentEngine->Type.Port.State == LinkStateVcoNegotiation) ? "LinkStateVcoNegotiation " : (
858 (CurrentEngine->Type.Port.State == LinkStateGfxWorkaround) ? "LinkStateGfxWorkaround " : (
859 (CurrentEngine->Type.Port.State == LinkStateTrainingCompleted) ? "LinkStateTrainingComplete" : (
860 (CurrentEngine->Type.Port.State == LinkStateRetrain) ? "LinkStateRetrain " : (
861 (CurrentEngine->Type.Port.State == LinkStateResetExit) ? "LinkStateResetExit " : "Unknown")))))))))))))))))),
862 CurrentEngine->Type.Port.TimeStamp
863 );
864}
Arthur Heymans704ccaf2022-05-16 14:55:46 +0200865)