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