70215514e2fd87d1b6bfa083db632879a0ea12e8
[coreboot.git] / src / vendorcode / amd / agesa / f14 / Proc / GNB / Modules / GnbPcieConfig / PcieMapTopology.c
1 /* $NoKeywords:$ */
2 /**
3  * @file
4  *
5  * Procedure to map user define topology to processor configuration
6  *
7  *
8  *
9  * @xrefitem bom "File Content Label" "Release Content"
10  * @e project:     AGESA
11  * @e sub-project: GNB
12  * @e \$Revision: 39898 $   @e \$Date: 2010-10-15 17:08:45 -0400 (Fri, 15 Oct 2010) $
13  *
14  */
15 /*
16  *****************************************************************************
17  *
18  * Copyright (c) 2011, Advanced Micro Devices, Inc.
19  * All rights reserved.
20  * 
21  * 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.
28  *     * Neither the name of Advanced Micro Devices, Inc. nor the names of 
29  *       its contributors may be used to endorse or promote products derived 
30  *       from this software without specific prior written permission.
31  * 
32  * 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.
42  * 
43  * ***************************************************************************
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  "GnbPcieFamServices.h"
57 #include  "GeneralServices.h"
58 #include  "PcieInputParser.h"
59 #include  "PcieMapTopology.h"
60 #include  GNB_MODULE_DEFINITIONS (GnbPcieConfig)
61 #include  "Filecode.h"
62 #define FILECODE PROC_GNB_MODULES_GNBPCIECONFIG_PCIEMAPTOPOLOGY_FILECODE
63 /*----------------------------------------------------------------------------------------
64  *                   D E F I N I T I O N S    A N D    M A C R O S
65  *----------------------------------------------------------------------------------------
66  */
67
68
69 /*----------------------------------------------------------------------------------------
70  *                  T Y P E D E F S     A N D     S T R U C T U  R E S
71  *----------------------------------------------------------------------------------------
72  */
73
74
75 /*----------------------------------------------------------------------------------------
76  *           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
77  *----------------------------------------------------------------------------------------
78  */
79
80
81 AGESA_STATUS
82 STATIC
83 PcieMapPortsPciAddresses (
84   IN      PCIe_SILICON_CONFIG         *Silicon,
85   IN      PCIe_PLATFORM_CONFIG        *Pcie
86   );
87
88 AGESA_STATUS
89 PcieMapTopologyOnWrapper (
90   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
91   IN OUT  PCIe_WRAPPER_CONFIG         *Wrapper,
92   IN      PCIe_PLATFORM_CONFIG        *Pcie
93  );
94
95 VOID
96 PcieMapInitializeEngineData (
97   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
98   IN OUT  PCIe_WRAPPER_CONFIG         *Wrapper,
99   IN      PCIe_PLATFORM_CONFIG        *Pcie
100  );
101
102 BOOLEAN
103 PcieCheckPortPciDeviceMapping (
104   IN      PCIe_PORT_DESCRIPTOR  *PortDescriptor,
105   IN      PCIe_ENGINE_CONFIG    *Engine
106   );
107
108 VOID
109 PcieComplexConfigConfigDump (
110   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
111   IN      PCIe_PLATFORM_CONFIG        *Pcie
112   );
113
114 BOOLEAN
115 PcieIsDescriptorLinkWidthValid (
116   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor
117   );
118
119 BOOLEAN
120 PcieCheckLanesMatch (
121   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
122   IN      PCIe_ENGINE_CONFIG          *Engine
123   );
124
125 BOOLEAN
126 PcieCheckDescriptorMapsToWrapper (
127   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
128   IN      PCIe_WRAPPER_CONFIG         *Wrapper
129   );
130
131 VOID
132 PcieAllocateEngine (
133   IN      UINT8                       DescriptorIndex,
134   IN      PCIe_ENGINE_CONFIG          *Engine
135   );
136 /*----------------------------------------------------------------------------------------*/
137 /**
138  * Configure engine list to support lane allocation according to configuration ID.
139  *
140  *
141  *
142  * @param[in]  ComplexDescriptor   Pointer to used define complex descriptor
143  * @param[in]  Complex             Pointer to complex descriptor
144  * @param[in]  Pcie                Pointer to global PCIe configuration
145  * @retval     AGESA_SUCCESS       Topology successfully mapped
146  * @retval     AGESA_ERROR         Topology can not be mapped
147  */
148
149 AGESA_STATUS
150 PcieMapTopologyOnComplex (
151   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
152   IN      PCIe_COMPLEX_CONFIG         *Complex,
153   IN      PCIe_PLATFORM_CONFIG        *Pcie
154   )
155 {
156   PCIe_SILICON_CONFIG *Silicon;
157   PCIe_WRAPPER_CONFIG *Wrapper;
158   AGESA_STATUS        AgesaStatus;
159   AGESA_STATUS        Status;
160
161   AgesaStatus = AGESA_SUCCESS;
162   IDS_HDT_CONSOLE (GNB_TRACE, "PcieMapTopologyOnComplex Enter\n");
163   GNB_DEBUG_CODE (
164     PcieComplexConfigConfigDump (ComplexDescriptor, Pcie);
165   );
166   Silicon = PcieComplexGetSiliconList (Complex);
167   while (Silicon != NULL) {
168     Wrapper = PcieSiliconGetWrapperList (Silicon);
169     while (Wrapper != NULL) {
170       Status = PcieMapTopologyOnWrapper (ComplexDescriptor, Wrapper, Pcie);
171       AGESA_STATUS_UPDATE (Status, AgesaStatus);
172       if (Status == AGESA_ERROR) {
173         PcieConfigDisableAllEngines (PciePortEngine | PcieDdiEngine, Wrapper);
174         IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Fail to map topology on %s Wrapper\n",
175           PcieFmDebugGetWrapperNameString (Wrapper)
176           );
177         ASSERT (FALSE);
178       }
179       Wrapper = PcieLibGetNextDescriptor (Wrapper);
180     }
181     Status = PcieMapPortsPciAddresses (Silicon, Pcie);
182     AGESA_STATUS_UPDATE (Status, AgesaStatus);
183     Silicon = PcieLibGetNextDescriptor (Silicon);
184   }
185   IDS_HDT_CONSOLE (GNB_TRACE, "PcieMapTopologyOnComplex Exit [%x]\n", AgesaStatus);
186   return AgesaStatus;
187 }
188
189 /*----------------------------------------------------------------------------------------*/
190 /**
191  * Configure engine list to support lane allocation according to configuration ID.
192  *
193  *
194  *
195  * @param[in]  EngineType          Engine type
196  * @param[in]  ComplexDescriptor   Pointer to used define complex descriptor
197  * @param[in]  Wrapper             Pointer to wrapper config descriptor
198  * @retval     AGESA_SUCCESS       Topology successfully mapped
199  * @retval     AGESA_ERROR         Topology can not be mapped
200  */
201 AGESA_STATUS
202 PcieEnginesToWrapper (
203   IN      PCIE_ENGINE_TYPE            EngineType,
204   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
205   IN      PCIe_WRAPPER_CONFIG         *Wrapper
206   )
207 {
208   AGESA_STATUS                Status;
209   PCIe_ENGINE_CONFIG          *EngineList;
210   PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor;
211   UINT8                       ConfigurationId;
212   UINT8                       Allocations;
213   UINTN                       Index;
214   UINTN                       NumberOfDescriptors;
215
216   ConfigurationId = 0;
217   Allocations = 0;
218   IDS_HDT_CONSOLE (GNB_TRACE, "PcieEnginesToWrapper Enter\n");
219   NumberOfDescriptors = PcieInputParserGetNumberOfEngines (ComplexDescriptor);
220   do {
221     Status = PcieFmConfigureEnginesLaneAllocation (Wrapper, EngineType, ConfigurationId++);
222
223     if (Status == AGESA_SUCCESS) {
224       Allocations = 0;
225       for (Index = 0; Index < NumberOfDescriptors; Index++) {
226         EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, Index);
227         if (EngineDescriptor->EngineData.EngineType == EngineType) {
228           // Step 1, belongs to wrapper check.
229           if (PcieCheckDescriptorMapsToWrapper (EngineDescriptor, Wrapper)) {
230             ++Allocations;
231             EngineList = PcieWrapperGetEngineList (Wrapper);
232             while (EngineList != NULL) {
233               if (!PcieLibIsEngineAllocated (EngineList)) {
234                 // Step 2.user descriptor less or equal to link width of engine
235                 if (PcieCheckLanesMatch (EngineDescriptor, EngineList)) {
236                   // Step 3, Check if link width is correct.x1, x2, x4, x8, x16.
237                   if (!PcieIsDescriptorLinkWidthValid (EngineDescriptor)) {
238                     PcieConfigDisableEngine (EngineList);
239                     return AGESA_ERROR;
240                   }
241                   if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
242                     // Step 4, Family specifc, port device number match engine device
243                     if (PcieCheckPortPciDeviceMapping ((PCIe_PORT_DESCRIPTOR*) EngineDescriptor, EngineList)) {
244                       //Step 5, Family specifc, lanes can be muxed.
245                       if (PcieFmCheckPortPcieLaneCanBeMuxed ((PCIe_PORT_DESCRIPTOR*) EngineDescriptor, EngineList)) {
246                         PcieAllocateEngine ((UINT8) Index, EngineList);
247                         --Allocations;
248                       }
249                     }
250                   } else {
251                     PcieAllocateEngine ((UINT8) Index, EngineList);
252                     --Allocations;
253                   }
254                 }
255               }//end if PcieLibIsEngineAllocated
256               EngineList = PcieLibGetNextDescriptor (EngineList);
257             }
258           }//end if PcieCheckDescriptorMapsToWrapper
259         }// end if EngineType
260       }//end for
261     }
262   } while (Status == AGESA_SUCCESS && Allocations != 0);
263   IDS_HDT_CONSOLE (GNB_TRACE, "PcieEnginesToWrapper Exit [%x]\n", Status);
264   return Status;
265 }
266
267 /*----------------------------------------------------------------------------------------*/
268 /**
269  * Check if lane from  user port descriptor (PCIe_PORT_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
270  *
271  *
272  * @param[in]  EngineDescriptor    Pointer to used define engine descriptor
273  * @param[in]  Wrapper             Pointer to PCIe_WRAPPER_CONFIG
274  * @retval     TRUE                Belongs to wrapper
275  * @retval     FALSE               Not belongs to wrapper
276  */
277 BOOLEAN
278 PcieCheckDescriptorMapsToWrapper (
279   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
280   IN      PCIe_WRAPPER_CONFIG         *Wrapper
281   )
282 {
283   BOOLEAN Result;
284   UINT16  DescriptorHiLane;
285   UINT16  DescriptorLoLane;
286   UINT16  DescriptorNumberOfLanes;
287
288   DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
289   DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
290   DescriptorNumberOfLanes = DescriptorHiLane - DescriptorLoLane + 1;
291   Result = TRUE;
292
293   if (!(DescriptorLoLane >= Wrapper->StartPhyLane && DescriptorHiLane <= Wrapper->EndPhyLane)) {
294     // Lanes of descriptor does not belongs to wrapper
295     Result = FALSE;
296   }
297   return Result;
298 }
299
300 /*----------------------------------------------------------------------------------------*/
301 /**
302  * Set Engine to be allocated.
303  *
304  *
305  * @param[in]  DescriptorIndex    UINT8 index
306  * @param[in]  Engine             Pointer to engine config
307  */
308 VOID
309 PcieAllocateEngine (
310   IN      UINT8                       DescriptorIndex,
311   IN      PCIe_ENGINE_CONFIG          *Engine
312   )
313 {
314   Engine->Flags |= DESCRIPTOR_ALLOCATED;
315   Engine->Scratch = DescriptorIndex;
316 }
317
318 /*----------------------------------------------------------------------------------------*/
319 /**
320  * Configure engine list to support lane allocation according to configuration ID.
321  *
322  * PCIE port
323  *
324  *
325  * 1 Check if lane from  user port descriptor (PCIe_PORT_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
326  * 2 Check if link width from user descriptor less or equal to link width of engine (PCIe_ENGINE_CONFIG)
327  * 3 Check if link width is correct. Correct link width for PCIe port x1, x2, x4, x8, x16, correct link width for DDI x4, x8
328  * 4 Check if user port device number (PCIe_PORT_DESCRIPTOR) match engine port device number (PCIe_ENGINE_CONFIG)
329  * 5 Check if lane can be muxed
330  *
331  *
332  * DDI Link
333  *
334  * 1 Check if lane from  user port descriptor (PCIe_DDI_DESCRIPTOR) belongs to wrapper (PCIe_WRAPPER_CONFIG)
335  * 2 Check lane from  (PCIe_DDI_DESCRIPTOR) match exactly phy lane (PCIe_ENGINE_CONFIG)
336  *
337  *
338  *
339  * @param[in]     ComplexDescriptor   Pointer to used define complex descriptor
340  * @param[in,out] Wrapper             Pointer to wrapper config descriptor
341  * @param[in]     Pcie                Pointer to global PCIe configuration
342  * @retval        AGESA_SUCCESS       Topology successfully mapped
343  * @retval        AGESA_ERROR         Topology can not be mapped
344  */
345 AGESA_STATUS
346 PcieMapTopologyOnWrapper (
347   IN       PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
348   IN OUT   PCIe_WRAPPER_CONFIG         *Wrapper,
349   IN       PCIe_PLATFORM_CONFIG        *Pcie
350   )
351 {
352   AGESA_STATUS                AgesaStatus;
353   AGESA_STATUS                Status;
354   PCIe_ENGINE_CONFIG          *EngineList;
355   UINT32                      WrapperPhyLaneBitMap;
356
357   AgesaStatus = AGESA_SUCCESS;
358   if (PcieLibIsPcieWrapper (Wrapper)) {
359     Status = PcieEnginesToWrapper (PciePortEngine, ComplexDescriptor, Wrapper);
360     AGESA_STATUS_UPDATE (Status, AgesaStatus);
361     if (Status == AGESA_ERROR) {
362       // If we can not map topology on wrapper we can not enable any engines.
363       PutEventLog (
364         AGESA_ERROR,
365         GNB_EVENT_INVALID_PCIE_TOPOLOGY_CONFIGURATION,
366         Wrapper->WrapId,
367         Wrapper->StartPhyLane,
368         Wrapper->EndPhyLane,
369         0,
370         GnbLibGetHeader (Pcie)
371         );
372       PcieConfigDisableAllEngines (PciePortEngine, Wrapper);
373     }
374     EngineList = PcieWrapperGetEngineList (Wrapper);
375     // Assure SB is allocated
376     while (EngineList != NULL) {
377       if ((EngineList->EngineData.EngineType == PciePortEngine) && (EngineList->Type.Port.IsSB)) {
378         EngineList->Flags |= DESCRIPTOR_ALLOCATED;
379       }
380       EngineList = PcieLibGetNextDescriptor (EngineList);
381     }
382   }
383   if (PcieLibIsDdiWrapper (Wrapper)) {
384     Status = PcieEnginesToWrapper (PcieDdiEngine, ComplexDescriptor, Wrapper);
385     AGESA_STATUS_UPDATE (Status, AgesaStatus);
386     if (Status == AGESA_ERROR) {
387       // If we can not map topology on wrapper we can not enable any engines.
388       PutEventLog (
389         AGESA_ERROR,
390         GNB_EVENT_INVALID_DDI_TOPOLOGY_CONFIGURATION,
391         Wrapper->WrapId,
392         Wrapper->StartPhyLane,
393         Wrapper->EndPhyLane,
394         0,
395         GnbLibGetHeader (Pcie)
396         );
397       PcieConfigDisableAllEngines (PcieDdiEngine, Wrapper);
398     }
399   }
400   // Copy engine data
401   PcieMapInitializeEngineData (ComplexDescriptor, Wrapper, Pcie);
402
403   EngineList = PcieWrapperGetEngineList (Wrapper);
404   // Verify if we oversubscribe lanes and PHY link width
405   WrapperPhyLaneBitMap = 0;
406   while (EngineList != NULL) {
407     UINT32  EnginePhyLaneBitMap;
408     if (PcieLibIsEngineAllocated (EngineList)) {
409       EnginePhyLaneBitMap = PcieConfigGetEnginePhyLaneBitMap (EngineList);
410       if ((WrapperPhyLaneBitMap & EnginePhyLaneBitMap) != 0) {
411         IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Lanes double subscribe lanes [Engine Lanes %d..%d]\n",
412           EngineList->EngineData.StartLane,
413           EngineList->EngineData.EndLane
414           );
415         PutEventLog (
416           AGESA_ERROR,
417           GNB_EVENT_INVALID_LANES_CONFIGURATION,
418           EngineList->EngineData.StartLane,
419           EngineList->EngineData.EndLane,
420           0,
421           0,
422           GnbLibGetHeader (Pcie)
423           );
424         PcieConfigDisableEngine (EngineList);
425         Status = AGESA_ERROR;
426         AGESA_STATUS_UPDATE (Status, AgesaStatus);
427       } else {
428         WrapperPhyLaneBitMap |= EnginePhyLaneBitMap;
429       }
430     }
431     EngineList = PcieLibGetNextDescriptor (EngineList);
432   }
433   return AgesaStatus;
434 }
435
436
437 /*----------------------------------------------------------------------------------------*/
438 /**
439  * Initialize engine data
440  *
441  *
442  *
443  * @param[in]     ComplexDescriptor   Pointer to user defined complex descriptor
444  * @param[in,out] Wrapper             Pointer to wrapper config descriptor
445  * @param[in]     Pcie                Pointer to global PCIe configuration
446  */
447 VOID
448 PcieMapInitializeEngineData (
449   IN       PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
450   IN OUT   PCIe_WRAPPER_CONFIG         *Wrapper,
451   IN       PCIe_PLATFORM_CONFIG        *Pcie
452   )
453 {
454   PCIe_ENGINE_CONFIG        *EngineList;
455   PCIe_ENGINE_DESCRIPTOR    *EngineDescriptor;
456
457   EngineList = PcieWrapperGetEngineList (Wrapper);
458   while (EngineList != NULL) {
459     if (PcieLibIsEngineAllocated (EngineList)) {
460       if (EngineList->Scratch != 0xFF) {
461         EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, EngineList->Scratch);
462         LibAmdMemCopy (&EngineList->EngineData, &EngineDescriptor->EngineData, sizeof (EngineDescriptor->EngineData), GnbLibGetHeader (Pcie));
463         if (PcieLibIsDdiEngine (EngineList)) {
464           LibAmdMemCopy (&EngineList->Type.Ddi, &((PCIe_DDI_DESCRIPTOR*) EngineDescriptor)->Ddi, sizeof (PCIe_DDI_DATA), GnbLibGetHeader (Pcie));
465           EngineList->Type.Ddi.DisplayPriorityIndex = (UINT8) EngineList->Scratch;
466         } else if (PcieLibIsPcieEngine (EngineList)) {
467           LibAmdMemCopy (&EngineList->Type.Port, &((PCIe_PORT_DESCRIPTOR*) EngineDescriptor)->Port, sizeof (PCIe_PORT_DATA), GnbLibGetHeader (Pcie));
468         }
469       }
470     }
471     EngineList = PcieLibGetNextDescriptor (EngineList);
472   }
473 }
474
475 /*----------------------------------------------------------------------------------------*/
476 /**
477  * Allocate PCI addresses for all PCIe engines on silicon
478  *
479  *
480  *
481  * @param[in]  PortDescriptor      Pointer to user defined engine descriptor
482  * @param[in]  Engine              Pointer engine configuration
483  * @retval     TRUE                Descriptor can be mapped to engine
484  * @retval     FALSE               Descriptor can NOT be mapped to engine
485  */
486
487 BOOLEAN
488 PcieCheckPortPciDeviceMapping (
489   IN      PCIe_PORT_DESCRIPTOR  *PortDescriptor,
490   IN      PCIe_ENGINE_CONFIG    *Engine
491   )
492 {
493   BOOLEAN Result;
494
495   if ((PortDescriptor->Port.DeviceNumber == Engine->Type.Port.NativeDevNumber &&
496     PortDescriptor->Port.FunctionNumber == Engine->Type.Port.NativeFunNumber) ||
497     (PortDescriptor->Port.DeviceNumber == 0 && PortDescriptor->Port.FunctionNumber == 0)) {
498     Result = TRUE;
499   } else {
500     Result = PcieFmCheckPortPciDeviceMapping (PortDescriptor, Engine);
501   }
502
503   return Result;
504 }
505
506 /*----------------------------------------------------------------------------------------*/
507 /**
508  * Allocate PCI addresses for all PCIe engines on silicon
509  *
510  *
511  *
512  * @param[in]  Silicon             Pointer to silicon configurration
513  * @param[in]  Pcie                Pointer PCIe configuration
514  * @retval     AGESA_ERROR         Fail to allocate PCI device address
515  * @retval     AGESA_SUCCESS       Successfully allocate PCI address for all PCIe ports
516  */
517
518 AGESA_STATUS
519 STATIC
520 PcieMapPortsPciAddresses (
521   IN      PCIe_SILICON_CONFIG    *Silicon,
522   IN      PCIe_PLATFORM_CONFIG   *Pcie
523   )
524 {
525   AGESA_STATUS        Status;
526   AGESA_STATUS        AgesaStatus;
527   PCIe_WRAPPER_CONFIG *WrapperList;
528   PCIe_ENGINE_CONFIG  *EngineList;
529   AgesaStatus = AGESA_SUCCESS;
530   WrapperList = PcieSiliconGetWrapperList (Silicon);
531   while (WrapperList != NULL) {
532     EngineList = PcieWrapperGetEngineList (WrapperList);
533     while (EngineList != NULL) {
534       if (PcieLibIsPcieEngine (EngineList) && PcieLibIsEngineAllocated (EngineList)) {
535         Status = PcieFmMapPortPciAddress (EngineList, Pcie);
536         AGESA_STATUS_UPDATE (Status, AgesaStatus);
537         if (Status == AGESA_SUCCESS) {
538           EngineList->Type.Port.Address.AddressValue = MAKE_SBDFO (
539                                                          0,
540                                                          Silicon->Address.Address.Bus,
541                                                          EngineList->Type.Port.PortData.DeviceNumber,
542                                                          EngineList->Type.Port.PortData.FunctionNumber,
543                                                          0
544                                                          );
545         } else {
546           EngineList->Type.Port.PortData.PortPresent = OFF;
547           IDS_HDT_CONSOLE (PCIE_MISC, "  ERROR! Fail to allocate PCI address for PCIe port\n"
548             );
549           //Report error
550           PutEventLog (
551             AGESA_ERROR,
552             GNB_EVENT_INVALID_PCIE_PORT_CONFIGURATION,
553             EngineList->Type.Port.PortData.DeviceNumber,
554             0,
555             0,
556             0,
557             GnbLibGetHeader (Pcie)
558             );
559         }
560       }
561       EngineList = PcieLibGetNextDescriptor (EngineList);
562     }
563     WrapperList = PcieLibGetNextDescriptor (WrapperList);
564   }
565   return AgesaStatus;
566 }
567
568 /*----------------------------------------------------------------------------------------*/
569 /**
570  * If link width from user descriptor less or equal to link width of engine
571  *
572  *
573  * @param[in]  EngineDescriptor    Pointer to used define engine descriptor
574  * @param[in]  Engine              Pointer to engine config
575  * @retval     TRUE                Descriptor can be mapped to engine
576  * @retval     FALSE               Descriptor can NOT be mapped to engine
577  */
578
579 BOOLEAN
580 PcieCheckLanesMatch (
581   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor,
582   IN      PCIe_ENGINE_CONFIG          *Engine
583   )
584 {
585   BOOLEAN Result;
586   UINT16  DescriptorHiLane;
587   UINT16  DescriptorLoLane;
588   UINT16  DescriptorNumberOfLanes;
589
590   DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
591   DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
592   DescriptorNumberOfLanes = DescriptorHiLane - DescriptorLoLane + 1;
593   Result = FALSE;
594
595   if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
596     //
597     // If link width from user descriptor less or equal to link width of engine (PCIe_ENGINE_CONFIG)
598     //
599     if (DescriptorNumberOfLanes <= PcieConfigGetNumberOfCoreLane (Engine)) {
600       Result = TRUE;
601     }
602   } else if (EngineDescriptor->EngineData.EngineType == PcieDdiEngine) {
603     //
604     //For Ddi, check lane from  (PCIe_DDI_DESCRIPTOR) match exactly phy lane (PCIe_ENGINE_CONFIG)
605     //
606     if ((Engine->EngineData.StartLane == DescriptorLoLane) && (Engine->EngineData.EndLane == DescriptorHiLane)) {
607       Result = TRUE;
608     }
609   }
610
611   return Result;
612 }
613
614 /*----------------------------------------------------------------------------------------*/
615 /**
616  * Correct link width for PCIe port x1, x2, x4, x8, x16, correct link width for DDI x4, x8
617  *
618  *
619  * @param[in]  EngineDescriptor    A pointer of PCIe_ENGINE_DESCRIPTOR
620  * @retval     TRUE                Descriptor can be mapped to engine
621  * @retval     FALSE               Descriptor can NOT be mapped to engine
622  */
623
624 BOOLEAN
625 PcieIsDescriptorLinkWidthValid (
626   IN      PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor
627   )
628 {
629   BOOLEAN   Result;
630   UINT16    DescriptorHiLane;
631   UINT16    DescriptorLoLane;
632   UINT16    DescriptorNumberOfLanes;
633
634   Result = FALSE;
635   DescriptorLoLane = MIN (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
636   DescriptorHiLane = MAX (EngineDescriptor->EngineData.StartLane, EngineDescriptor->EngineData.EndLane);
637   DescriptorNumberOfLanes = DescriptorHiLane - DescriptorLoLane + 1;
638
639   if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
640     if (DescriptorNumberOfLanes == 1 || DescriptorNumberOfLanes == 2 || DescriptorNumberOfLanes == 4 ||
641         DescriptorNumberOfLanes == 8 || DescriptorNumberOfLanes == 16) {
642       Result = TRUE;
643     }
644   } else if (EngineDescriptor->EngineData.EngineType == PcieDdiEngine) {
645     if (DescriptorNumberOfLanes == 4 || DescriptorNumberOfLanes == 8) {
646       Result = TRUE;
647     }
648   }
649
650   GNB_DEBUG_CODE (
651     if (!Result) {
652       IDS_HDT_CONSOLE (PCIE_MISC, "  Invalid Link width [Engine Lanes %d..%d]\n",
653         DescriptorLoLane,
654         DescriptorHiLane
655       );
656     }
657   );
658
659   return Result;
660 }
661
662 /*----------------------------------------------------------------------------------------*/
663 /**
664  * Helper function to dump input configuration to debug out
665  *
666  *
667  * @param[in]  ComplexDescriptor   Pointer to used define complex descriptor
668  * @param[in]  Pcie                Pointer to global PCIe configuration
669  */
670 VOID
671 PcieComplexConfigConfigDump (
672   IN      PCIe_COMPLEX_DESCRIPTOR     *ComplexDescriptor,
673   IN      PCIe_PLATFORM_CONFIG        *Pcie
674   )
675 {
676   PCIe_ENGINE_DESCRIPTOR      *EngineDescriptor;
677   UINTN                       Index;
678   UINTN                       NumberOfEngines;
679   IDS_HDT_CONSOLE (PCIE_MISC, "<---------- PCIe User Config Start------------->\n");
680
681   NumberOfEngines = PcieInputParserGetNumberOfEngines (ComplexDescriptor);
682   IDS_HDT_CONSOLE (PCIE_MISC, "  ComplexDescriptor SocketId - %d\n  NumberOfEngines - %d\n",
683       ComplexDescriptor->SocketId,
684       NumberOfEngines
685     );
686
687   for (Index = 0; Index < NumberOfEngines; Index++) {
688     EngineDescriptor = PcieInputParserGetEngineDescriptor (ComplexDescriptor, Index);
689     IDS_HDT_CONSOLE (PCIE_MISC, "  Engine Type - %s\n",
690       (EngineDescriptor->EngineData.EngineType == PciePortEngine) ? "PCIe Port" : (
691       (EngineDescriptor->EngineData.EngineType == PcieDdiEngine) ? "DDI Link" : (
692       (EngineDescriptor->EngineData.EngineType == PcieUnusedEngine) ? "Unused" : "Invalid"))
693       );
694     IDS_HDT_CONSOLE (PCIE_MISC, "    Start Phy Lane - %d\n    End   Phy Lane - %d\n",
695       EngineDescriptor->EngineData.StartLane,
696       EngineDescriptor->EngineData.EndLane
697     );
698     if (EngineDescriptor->EngineData.EngineType == PciePortEngine) {
699       IDS_HDT_CONSOLE (PCIE_MISC, "    PortPresent - %d\n    ChannelType  - %d\n    DeviceNumber - %d\n    FunctionNumber - %d\n    LinkSpeedCapability - %d\n    LinkAspm - %d\n    LinkHotplug - %d\n    ResetId - %d\n" ,
700         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.PortPresent,
701         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.ChannelType,
702         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.DeviceNumber,
703         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.FunctionNumber,
704         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.LinkSpeedCapability,
705         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.LinkAspm,
706         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.LinkHotplug,
707         ((PCIe_PORT_DESCRIPTOR *) EngineDescriptor)->Port.ResetId
708       );
709     }
710     if (EngineDescriptor->EngineData.EngineType == PcieDdiEngine) {
711       IDS_HDT_CONSOLE (PCIE_MISC, "    ConnectorType - %d\n    AuxIndex  - %d\n    HdpIndex - %d\n" ,
712         ((PCIe_DDI_DESCRIPTOR *) EngineDescriptor)->Ddi.ConnectorType,
713         ((PCIe_DDI_DESCRIPTOR *) EngineDescriptor)->Ddi.AuxIndex,
714         ((PCIe_DDI_DESCRIPTOR *) EngineDescriptor)->Ddi.HdpIndex
715       );
716     }
717   }
718   IDS_HDT_CONSOLE (PCIE_MISC, "<---------- PCIe User Config End-------------->\n");
719 }
720