2 QNC PCI Express initialization entry
4 Copyright (c) 2013-2015 Intel Corporation.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "CommonHeader.h"
18 #define PCIEXP_ROOT_PORT_URE_ENABLE BIT0 // unsupported request reporting enable
19 #define PCIEXP_ROOT_PORT_FEE_ENABLE BIT1 // Fatal Error Reporting Enable
20 #define PCIEXP_ROOT_PORT_NFE_ENABLE BIT2 // Non-Fatal Error Reporting Enable
21 #define PCIEXP_ROOT_PORT_CEE_ENABLE BIT3 // Correctable Error Reporting Enable
22 #define PCIEXP_ROOT_PORT_SFE_ENABLE BIT4 // System Error on Fatal Error Enable
23 #define PCIEXP_ROOT_PORT_SNE_ENABLE BIT5 // System Error on Non-Fatal Error Enable
24 #define PCIEXP_ROOT_PORT_SCE_ENABLE BIT6 // System Error on Correctable Error Enable
31 MicroSecondDelay (Microseconds
);
37 Find the Offset to a given Capabilities ID
39 0x01 = PCI Power Management Interface
40 0x04 = Slot Identification
42 0x10 = PCI Express Capability
44 @param[in] Bus Bus number of the interested device
45 @param[in] Device Device number of the interested device
46 @param[in] Function Function number of the interested device
47 @param[in] CapId Capability ID to be scanned
49 @retval Offset of desired CAPID
63 // Always start at Offset 0x34
65 CapHeader
= QNCMmPci8 (0, Bus
, Device
, Function
, R_QNC_PCIE_CAP_PTR
);
67 if (CapHeader
== 0xFF) {
71 while (CapHeader
!= 0) {
72 if (QNCMmPci8 (0, Bus
, Device
, Function
, CapHeader
) == CapId
) {
75 CapHeader
= QNCMmPci8 (0, Bus
, Device
, Function
, CapHeader
+ 1);
82 Search and return the offset of desired Pci Express Capability ID
84 0x0001 = Advanced Error Rreporting Capability
85 0x0002 = Virtual Channel Capability
86 0x0003 = Device Serial Number Capability
87 0x0004 = Power Budgeting Capability
89 @param[in] Bus Bus number of the interested device
90 @param[in] Device Device number of the interested device
91 @param[in] Function Function number of the interested device
92 @param[in] CapId Capability ID to be scanned
94 @retval Offset of desired CAPID
98 PcieFindExtendedCapId (
105 UINT16 CapHeaderOffset
;
108 // Start to search at Offset 0x100
109 // Get Capability Header
111 CapHeaderOffset
= PCIE_CAP_EXT_HEARDER_OFFSET
;
113 while (CapHeaderOffset
!= 0 && CapHeaderId
!= 0xFFFF) {
114 CapHeaderId
= QNCMmPci16 (0, Bus
, Device
, Function
, CapHeaderOffset
);
115 if (CapHeaderId
== CapId
) {
116 return CapHeaderOffset
;
118 CapHeaderOffset
= (QNCMmPci16 (0, Bus
, Device
, Function
, CapHeaderOffset
+ 2) >> 4);
125 Map Vc on both root port and downstream device
127 @param[in] Bus1 Bus number of the root port
128 @param[in] Device1 Device number of the root port
129 @param[in] Function1 Function number of the root port
130 @param[in] Bus2 Bus number of the downstream device
131 @param[in] Device2 Device number of the downstream device
132 @param[in] Function2 Function number of the downstream device
134 @retval EFI_SUCCESS Map Vc successful
150 // Initialize TCx-VC0 value on the port to only use TC0
152 Offset
= PcieFindExtendedCapId (Bus1
, Device1
, Function1
, 2);
154 return EFI_UNSUPPORTED
;
156 QNCMmPci8AndThenOr (0, Bus1
, Device1
, Function1
, (Offset
+ PCIE_SLOT_CAP_OFFSET
), ~0xF, 1);
158 // Set TCx-VC0 value on the Endpoint
160 Offset
= PcieFindExtendedCapId (Bus2
, Device2
, Function2
, 2);
162 return EFI_UNSUPPORTED
;
164 QNCMmPci8AndThenOr (0, Bus2
, Device2
, Function2
, (Offset
+ PCIE_SLOT_CAP_OFFSET
), ~0xF, 1);
171 Map Traffic Class x to Vc0 on both root port and downstream device
173 @param[in] Bus1 Bus number of the root port
174 @param[in] Device1 Device number of the root port
175 @param[in] Function1 Function number of the root port
176 @param[in] Bus2 Bus number of the downstream device
177 @param[in] Device2 Device number of the downstream device
178 @param[in] Function2 Function number of the downstream device
179 @param[in] TCx Traffic Class to be mapped to vc0
181 @retval EFI_SUCCESS Map Tcx to Vc0 successful
198 // Set TCx-VC0 value on the port
201 Offset
= PcieFindExtendedCapId (Bus1
, Device1
, Function1
, 2);
203 return EFI_UNSUPPORTED
;
205 QNCMmPci8 (0, Bus1
, Device1
, Function1
, (Offset
+ PCIE_SLOT_CAP_OFFSET
)) = (UINT8
)(1 << TCx
);
207 // Set TCx-VC0 value on the Endpoint
209 Offset
= PcieFindExtendedCapId (Bus2
, Device2
, Function2
, 2);
211 return EFI_UNSUPPORTED
;
213 QNCMmPci8 (0, Bus2
, Device2
, Function2
, (Offset
+ PCIE_SLOT_CAP_OFFSET
)) = (UINT8
)(1 << TCx
);
220 Set common clock for both root port and downstream device.
222 @param[in] Bus1 Bus number of the root port
223 @param[in] Device1 Device number of the root port
224 @param[in] Function1 Function number of the root port
225 @param[in] Bus2 Device number of the downstream device
226 @param[in] Device2 Function number of the downstream device
228 @retval EFI_SUCCESS Set common clock successful
247 // Get the pointer to the Port PCI Express Capability Structure.
250 CapOffset1
= PcieFindCapId (Bus1
, Device1
, Function1
, PCIE_CAPID
);
251 if (CapOffset1
== 0) {
252 return EFI_UNSUPPORTED
;
257 // Read the Slot Clock Configuration bit of the Link status register of the root port and the endpoint device connected to the port
258 // If both components have this bit set to 1, then System BIOS should set the "Common Clock Configuration" bit in the Link Control Registers
259 // for both components at both sides of the link to indicate that components at both ends
260 // of the link use a common clock source
264 // Check the Port Slot Clock Configuration Bit.
266 if ((QNCMmPci16 (0, Bus1
, Device1
, Function1
, (CapOffset1
+ PCIE_LINK_STS_OFFSET
)) & B_QNC_PCIE_LSTS_SCC
) == 0) {
267 return EFI_UNSUPPORTED
;
270 for (Function2
= 0; Function2
< 8; Function2
++) {
272 // Check the Endpoint Slot Clock Configuration Bit.
274 CapOffset2
= PcieFindCapId (Bus2
, Device2
, Function2
, PCIE_CAPID
);
275 if ((CapOffset2
!= 0) &&
276 ((QNCMmPci16 (0, Bus2
, Device2
, Function2
, (CapOffset2
+ PCIE_LINK_STS_OFFSET
)) & B_QNC_PCIE_LSTS_SCC
) != 0)) {
279 // Common clock is supported, set common clock bit on root port
282 if (CommonClock
== 0) {
283 QNCMmPci8Or (0, Bus1
, Device1
, Function1
, (CapOffset1
+ PCIE_LINK_CNT_OFFSET
), B_QNC_PCIE_LCTL_CCC
);
286 QNCMmPci8Or (0, Bus2
, Device2
, Function2
, (CapOffset2
+ PCIE_LINK_CNT_OFFSET
), B_QNC_PCIE_LCTL_CCC
);
291 // Step 2 If the Common Clock Configuration bit was changed by BIOS in step 1,
292 // System BIOS should initiate a link training by setting the Retrain Link bit
293 // in the Link Control register of the root port (D28:F0/F1 offset
294 // 50h [5]) to "1b" and then poll the Link Training bit in the Link Status
295 // register of the root port (D28:F0/F1/F2/F3/F4/F5 offset 52h [11]) until it is
298 if (CommonClock
== 0) {
299 Status
= EFI_UNSUPPORTED
;
302 // Retrain the Link per PCI Express Specification.
304 QNCMmPci8Or (0, Bus1
, Device1
, Function1
, (CapOffset1
+ PCIE_LINK_CNT_OFFSET
), B_QNC_PCIE_LCTL_RL
);
307 // Wait until Re-Training has completed.
309 while ((QNCMmPci16 (0, Bus1
, Device1
, Function1
, (CapOffset1
+ PCIE_LINK_STS_OFFSET
)) & B_QNC_PCIE_LSTS_LT
) != 0);
310 Status
= EFI_SUCCESS
;
318 Enables the CLKREQ# PM on all the end point functions
320 @param[in] Bus Bus number of the downstream device
321 @param[in] Device Device number of the downstream device
336 // Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
337 // exists then enable the CLKREQ# bit (BIT8) on that function
339 for (Function
= 0; Function
< 8; Function
++) {
341 // Find the PCIe Cap Id (offset 10h)
343 CapOffset
= PcieFindCapId (Bus
, Device
, Function
, PCIE_CAPID
);
344 if (CapOffset
== 0) {
349 // Check if CLKREQ# is supported by the endpoints
351 if ((QNCMmPci32 (0, Bus
, Device
, Function
, (CapOffset
+ PCIE_LINK_CAP_OFFSET
))
352 & B_QNC_PCIE_LCAP_CPM
) != B_QNC_PCIE_LCAP_CPM
) {
354 // CLKREQ# is not supported so dont do anything
361 // Now enable the CLKREQ#
363 for (Function
= 0; Function
< 8; Function
++) {
365 // Find the PCIe Cap Id (offset 10h)
367 CapOffset
= PcieFindCapId (Bus
, Device
, Function
, PCIE_CAPID
);
368 if (CapOffset
== 0) {
372 QNCMmPci16Or (0, Bus
, Device
, Function
, (CapOffset
+ PCIE_LINK_CNT_OFFSET
), BIT8
);
378 Configure ASPM automatically for both root port and downstream device.
380 @param[in] RootBus Bus number of the root port
381 @param[in] RootDevice Device number of the root port
382 @param[in] RootFunction Function number of the root port
383 @param[in] EndpointBus Bus number of the downstream device
384 @param[in] EndpointDevice Device number of the downstream device
385 @param[in] EndpointFunction Function number of the downstream device
386 @param[in] LinkAspmVal Currently used ASPM setting
388 @retval EFI_SUCCESS Configure ASPM successful
395 IN UINT8 RootFunction
,
396 IN UINT8 EndpointBus
,
397 IN UINT8 EndpointDevice
,
398 IN UINT8 EndpointFunction
,
399 OUT UINT16
*LinkAspmVal
402 UINT32 RootPcieCapOffset
;
403 UINT32 EndpointPcieCapOffset
;
406 UINT16 EndPointVendorId
;
407 UINT16 EndPointDeviceId
;
411 UINT32 EndPointLxLat
;
415 // Get the pointer to the Port PCI Express Capability Structure.
417 RootPcieCapOffset
= PcieFindCapId (RootBus
, RootDevice
, RootFunction
, PCIE_CAPID
);
418 if (RootPcieCapOffset
== 0) {
419 return EFI_UNSUPPORTED
;
423 // Get the pointer to the Endpoint PCI Express Capability Structure.
425 EndpointPcieCapOffset
= PcieFindCapId (EndpointBus
, EndpointDevice
, EndpointFunction
, PCIE_CAPID
);
426 if (EndpointPcieCapOffset
== 0) {
427 return EFI_UNSUPPORTED
;
431 // Obtain initial ASPM settings from respective port capability registers.
433 RootPortAspm
= (QNCMmPci16 (0, RootBus
, RootDevice
, RootFunction
, (RootPcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_APMS_MASK
) >> V_QNC_PCIE_LCAP_APMS_OFFSET
;
436 // Configure downstream device if present.
438 EndPointAspm
= (QNCMmPci16 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, (EndpointPcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_APMS_MASK
) >> V_QNC_PCIE_LCAP_APMS_OFFSET
;
441 // Mask APMC with values from lookup table.
442 // RevID of 0xFF applies to all steppings.
445 EndPointVendorId
= QNCMmPci16 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, 0);
446 EndPointDeviceId
= QNCMmPci16 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, 2);
447 EndPointRevId
= QNCMmPci8 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, 8);
449 // TODO: Mask with latency/acceptable latency comparison results.
451 AspmVal
= RootPortAspm
;
452 if (RootPortAspm
> EndPointAspm
) {
453 AspmVal
= EndPointAspm
;
457 // Check if L1 should be enabled based on port and endpoint L1 exit latency.
460 PortLxLat
= QNCMmPci32 (0, RootBus
, RootDevice
, RootFunction
, (RootPcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_EL1_MASK
;
461 EndPointLxLat
= QNCMmPci32 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, (EndpointPcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_EL1_MASK
;
464 if(PortLxLat
< EndPointLxLat
) {
465 LxLat
= EndPointLxLat
;
469 // check if the value is bigger than endpoint L1 acceptable exit latency, if it is
470 // larger than accepted value, then we should disable L1
473 if(LxLat
> (QNCMmPci32 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, (EndpointPcieCapOffset
+ PCIE_DEV_CAP_OFFSET
)) & B_QNC_PCIE_DCAP_E1AL
)) {
479 // Check if L0s should be enabled based on port and endpoint L0s exit latency.
482 PortLxLat
= QNCMmPci32 (0, RootBus
, RootDevice
, RootFunction
, (RootPcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_EL0_MASK
;
483 EndPointLxLat
= QNCMmPci32 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, (EndpointPcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_EL0_MASK
;
486 if(PortLxLat
< EndPointLxLat
) {
487 LxLat
= EndPointLxLat
;
491 // check if the value is bigger than endpoint L0s acceptable exit latency, if it is
492 // larger than accepted value, then we should disable L0s
495 if(LxLat
> (QNCMmPci32 (0, EndpointBus
, EndpointDevice
, EndpointFunction
, (EndpointPcieCapOffset
+ PCIE_DEV_CAP_OFFSET
)) & B_QNC_PCIE_DCAP_E0AL
)) {
500 RootPortAspm
= AspmVal
;
502 *LinkAspmVal
= AspmVal
;
506 QNCMmPci16AndThenOr (0, EndpointBus
, EndpointDevice
, EndpointFunction
, (EndpointPcieCapOffset
+ PCIE_LINK_CNT_OFFSET
), 0xFFFC, AspmVal
);
510 // Set Root Port Aspm
512 QNCMmPci16AndThenOr (0, RootBus
, RootDevice
, RootFunction
, (RootPcieCapOffset
+ PCIE_LINK_CNT_OFFSET
), 0xFFFC, RootPortAspm
);
519 Configure ASPM based on the given setting for the interested device.
521 @param[in] Bus Bus number of the interested device
522 @param[in] Device Device number of the interested device
523 @param[in] Function Function number of the interested device
524 @param[in] AspmSetting Aspm setting
525 @param[in] LinkAspmVal Currently used ASPM setting
527 @retval EFI_SUCCESS Configure ASPM successful
535 IN UINT8 AspmSetting
,
536 OUT UINT16
*LinkAspmVal
539 UINT32 PcieCapOffset
;
543 // Get the pointer to the Port PCI Express Capability Structure.
545 PcieCapOffset
= PcieFindCapId (Bus
, Device
, Function
, PCIE_CAPID
);
546 if (PcieCapOffset
== 0) {
547 return EFI_UNSUPPORTED
;
550 // Read the Link Capability register's ASPM setting
551 PortAspm
= (QNCMmPci16 (0, Bus
, Device
, Function
, (PcieCapOffset
+ PCIE_LINK_CAP_OFFSET
)) & B_QNC_PCIE_LCAP_APMS_MASK
) >> V_QNC_PCIE_LCAP_APMS_OFFSET
;
552 // Mask it with the Setup selection
553 PortAspm
&= AspmSetting
;
555 *LinkAspmVal
= PortAspm
;
556 // Write it to the Link Control register
557 QNCMmPci16AndThenOr (0, Bus
, Device
, Function
, (PcieCapOffset
+ PCIE_LINK_CNT_OFFSET
), 0xFFFC, PortAspm
);
564 Perform Initialization on one PCI Express root port.
566 @param[in] RootPortIndex Index of PCI Express root port
567 @param[in] RootPortConfig Pointer to the given pcie root port configuration
568 @param[in] PciExpressBar Base address of pcie space
569 @param[in] QNCRootComplexBar Base address of root complex
570 @param[in] QNCPmioBase Base address of PM IO space
571 @param[in] QNCGpeBase Base address of gpe IO space
573 @retval EFI_SUCCESS Initialization successful
578 IN UINT32 RootPortIndex
,
579 IN PCIEXP_ROOT_PORT_CONFIGURATION
*RootPortConfig
,
580 IN UINT64 PciExpressBar
,
581 IN UINT32 QNCRootComplexBar
,
582 IN UINT32 QNCPmioBase
,
595 RPBase
= PciExpressBar
+ (((PCI_BUS_NUMBER_QNC
<< 8) + ((PCI_DEVICE_NUMBER_PCIE_ROOTPORT
) << 3) + ((PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
) << 0)) << 12);
596 LpcBase
= PciExpressBar
+ (((PCI_BUS_NUMBER_QNC
<< 8) + (31 << 3) + (0 << 0)) << 12);
597 CapOffset
= PcieFindCapId (PCI_BUS_NUMBER_QNC
, (UINT8
)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT
), (UINT8
)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
), PCIE_CAPID
);
599 if (CapOffset
== 0) {
600 return EFI_UNSUPPORTED
;
604 // Initialize "Slot Implmemented Bit" for this root port
606 if (RootPortConfig
[RootPortIndex
].Bits
.SlotImplemented
) {
607 QNCMmio16Or (RPBase
, R_QNC_PCIE_XCAP
, B_QNC_PCIE_XCAP_SI
);
611 // For Root Port Slots Numbering on the CRBs.
612 // Root Port 0 = Slot 1
613 // Root Port 1 = Slot 2
614 // Root Port 2 = Slot 3
615 // Root Port 3 = Slot 4
617 DwordReg
= QNCMmio32 (RPBase
, R_QNC_PCIE_SLCAP
);
618 DwordReg
&= B_QNC_PCIE_SLCAP_MASK_RSV_VALUE
;
619 DwordReg
|= (V_QNC_PCIE_SLCAP_SLV
<< V_QNC_PCIE_SLCAP_SLV_OFFSET
);
620 DwordReg
|= ((RootPortConfig
[RootPortIndex
].Bits
.PhysicalSlotNumber
) << V_QNC_PCIE_SLCAP_PSN_OFFSET
) ;
621 QNCMmio32 (RPBase
, R_QNC_PCIE_SLCAP
) = DwordReg
;
624 // Check for a Presence Detect Change.
626 SlotStatus
= QNCMmio16 (RPBase
, R_QNC_PCIE_SLSTS
);
627 if ((SlotStatus
& (B_QNC_PCIE_SLSTS_PDS
+ B_QNC_PCIE_SLSTS_PDC
)) == 0) {
628 return EFI_NOT_FOUND
;
632 // Temporarily Hardcode the Root Port Bridge Number to 2.
634 // This Endpoint check should immediately pass. Howerver, a 900ms delay
635 // has been added to match the timing requirements of the PCI Express Base
636 // Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s
637 // after a reset of a device, before it may determine that a device which
638 // fails to return a Successful Completion status for a valid Configuration
639 // Request is a broken device"). Note that a 100ms delay was already added
640 // after the Root Ports were first taken out of reset.
642 QNCMmio32AndThenOr (RPBase
, R_QNC_PCIE_BNUM
, 0xFF0000FF, 0x00020200);
644 // Only do this when a downstream device is present
646 EndPointBase
= PciExpressBar
+ (((2 << 8) + (0 << 3) + (0 << 0)) << 12);
647 if ((SlotStatus
& B_QNC_PCIE_SLSTS_PDS
) != 0) {
648 for (Index
= 0; Index
< V_PCIE_MAX_TRY_TIMES
; Index
++){
649 if (QNCMmio16 (EndPointBase
, 0x0) != 0xFFFF) {
654 if (Index
>= V_PCIE_MAX_TRY_TIMES
) {
656 // Clear Bus Numbers.
658 QNCMmio32And (RPBase
, R_QNC_PCIE_BNUM
, 0xFF0000FF);
659 return EFI_NOT_FOUND
;
664 // PCI Express* Virtual Channels
665 // Clear TC1-7 Traffic classes.
668 PcieInitTcxVc0 (PCI_BUS_NUMBER_QNC
, (UINT8
)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT
), (UINT8
)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
), 2, 0, 0);
669 PcieMapTcxVc0 (PCI_BUS_NUMBER_QNC
, (UINT8
)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT
), (UINT8
)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
), 2, 0, 0, 0x0);
672 // Set Common Clock for inserted cards
674 if ((SlotStatus
& B_QNC_PCIE_SLSTS_PDS
) != 0) {
675 PcieSetCommonClock (PCI_BUS_NUMBER_QNC
, (UINT8
)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT
), (UINT8
)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
), 2, 0);
679 // Flow for Enabling ASPM
681 if (RootPortConfig
[RootPortIndex
].Bits
.AspmEnable
) {
682 if (RootPortConfig
[RootPortIndex
].Bits
.AspmAutoEnable
) {
683 PcieSetAspmAuto (PCI_BUS_NUMBER_QNC
, (UINT8
)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT
), (UINT8
)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
), 2, 0, 0, &AspmVal
);
686 // Set ASPM values according to setup selections, masked by capabilities
690 (UINT8
) (PCI_DEVICE_NUMBER_PCIE_ROOTPORT
),
691 (UINT8
) (PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
+ RootPortIndex
),
692 (UINT8
) ((RootPortConfig
[RootPortIndex
].Bits
.AspmL0sEnable
& 0x01) | (RootPortConfig
[RootPortIndex
].Bits
.AspmL1Enable
<< 1)),
699 // Enable the PCIe CLKREQ#
701 if ((SlotStatus
& B_QNC_PCIE_SLSTS_PDS
) != 0) {
702 PcieSetClkreq (2, 0);
708 QNCMmio32And (RPBase
, R_QNC_PCIE_BNUM
, 0xFF0000FF);
711 // Additional configurations
715 // PCI-E Unsupported Request Reporting Enable
717 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_URE_ENABLE
) {
718 QNCMmio16Or (RPBase
, R_QNC_PCIE_DCTL
, B_QNC_PCIE_DCTL_URE
);
722 // Device Fatal Error Reporting Enable
724 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_FEE_ENABLE
) {
725 QNCMmio16Or (RPBase
, R_QNC_PCIE_DCTL
, B_QNC_PCIE_DCTL_FEE
);
729 // Device Non Fatal Error Reporting Enable
731 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_NFE_ENABLE
) {
732 QNCMmio16Or (RPBase
, R_QNC_PCIE_DCTL
, B_QNC_PCIE_DCTL_NFE
);
736 // Device Correctable Error Reporting Enable
738 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_CEE_ENABLE
) {
739 QNCMmio16Or (RPBase
, R_QNC_PCIE_DCTL
, B_QNC_PCIE_DCTL_CEE
);
742 // Root PCI-E PME Interrupt Enable
744 if (RootPortConfig
[RootPortIndex
].Bits
.PmeInterruptEnable
) {
745 QNCMmio16Or (RPBase
, R_QNC_PCIE_RCTL
, B_QNC_PCIE_RCTL_PIE
);
748 // Root PCI-E System Error on Fatal Error Enable
750 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_SFE_ENABLE
) {
751 QNCMmio16Or (RPBase
, R_QNC_PCIE_RCTL
, B_QNC_PCIE_RCTL_SFE
);
755 // Root PCI-E System Error on Non-Fatal Error Enable
757 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_SNE_ENABLE
) {
758 QNCMmio16Or (RPBase
, R_QNC_PCIE_RCTL
, B_QNC_PCIE_RCTL_SNE
);
762 // Root PCI-E System Error on Correctable Error Enable
764 if (RootPortConfig
[RootPortIndex
].Bits
.PortErrorMask
& PCIEXP_ROOT_PORT_SCE_ENABLE
) {
765 QNCMmio16Or (RPBase
, R_QNC_PCIE_RCTL
, B_QNC_PCIE_RCTL_SCE
);
769 // Root PCI-E Powermanagement SCI Enabled
771 if (RootPortConfig
[RootPortIndex
].Bits
.PmSciEnable
) {
773 // Make sure that PME Interrupt Enable bit of Root Control register
774 // of PCI Express Capability struceture is cleared
776 QNCMmio32And (RPBase
, R_QNC_PCIE_RCTL
, (~B_QNC_PCIE_RCTL_PIE
));
777 QNCMmio32AndThenOr (RPBase
, R_QNC_PCIE_MPC
, (~B_QNC_PCIE_MPC_PMME
), B_QNC_PCIE_MPC_PMCE
);
780 // Make sure GPE0 Stutus RW1C Bit is clear.
782 DwordReg
= IoRead32 (QNCGpeBase
+ R_QNC_GPE0BLK_GPE0S
);
783 if ((DwordReg
& B_QNC_GPE0BLK_GPE0S_PCIE
) != 0) {
784 IoWrite32 (QNCGpeBase
+ R_QNC_GPE0BLK_GPE0S
, B_QNC_GPE0BLK_GPE0S_PCIE
);
789 // PCIe Hot Plug SCI Enable
791 if (RootPortConfig
[RootPortIndex
].Bits
.HotplugSciEnable
) {
794 // Attention Button Pressed (bit0)
795 // Presence Detect Changed (bit3)
797 QNCMmio32Or (RPBase
, R_QNC_PCIE_SLSTS
, (B_QNC_PCIE_SLSTS_PDC
| B_QNC_PCIE_SLSTS_ABP
));
800 // Sequence 2: Program the following bits in Slot Control register at offset 18h
801 // of PCI Express* Capability structure:
802 // Attention Button Pressed Enable (bit0) = 1b
803 // Presence Detect Changed Enable (bit3) = 1b
804 // Hot Plug Interrupt Enable (bit5) = 0b
806 QNCMmio32AndThenOr (RPBase
, R_QNC_PCIE_SLCTL
, (~B_QNC_PCIE_SLCTL_HPE
), (B_QNC_PCIE_SLCTL_PDE
| B_QNC_PCIE_SLCTL_ABE
));
809 // Sequence 3: Program Misc Port Config (MPC) register at PCI config space offset
811 // Hot Plug SCI Enable (HPCE, bit30) = 1b
812 // Hot Plug SMI Enable (HPME, bit1) = 0b
814 QNCMmio32AndThenOr (RPBase
, R_QNC_PCIE_MPC
, (~B_QNC_PCIE_MPC_HPME
), B_QNC_PCIE_MPC_HPCE
);
823 Perform Initialization of the Downstream Root Ports
826 QNCDownStreamPortsInit (
827 IN PCIEXP_ROOT_PORT_CONFIGURATION
*RootPortConfig
,
828 IN QNC_DEVICE_ENABLES
*QNCDeviceEnables
,
829 IN UINT64 PciExpressBar
,
830 IN UINT32 QNCRootComplexBar
,
831 IN UINT32 QNCPmioBase
,
832 IN UINT32 QNCGpeBase
,
833 OUT UINTN
*RpEnableMask
840 // Initialize every root port and downstream device
842 for (Index
= 0;Index
< MAX_PCI_EXPRESS_ROOT_PORTS
;Index
++) {
843 if ((QNCDeviceEnables
->Uint32
& (1 << Index
)) != 0) {
844 Status
= QNCRootPortInit (
853 if (!EFI_ERROR (Status
)) {
854 (*RpEnableMask
) |= LShiftU64(1, Index
);
855 DEBUG ((EFI_D_INFO
, " Root Port %x device found, enabled. RpEnableMask: 0x%x\n", Index
+ 1, *RpEnableMask
));
862 Do early init of pci express rootports on Soc.
868 PciExpressEarlyInit (
873 // Setup Message Bus Idle Counter (SBIC) values.
875 QNCMmPci8(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_IOSFSBCTL
) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_IOSFSBCTL
, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK
), V_PCIE_ROOT_PORT_SBIC_VALUE
);
876 QNCMmPci8(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1
, R_QNC_PCIE_IOSFSBCTL
) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1
, R_QNC_PCIE_IOSFSBCTL
, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK
), V_PCIE_ROOT_PORT_SBIC_VALUE
);
879 // Program SVID/SID the same as VID/DID for Root ports.
881 QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_SVID
) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, PCI_VENDOR_ID_OFFSET
);
882 QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1
, R_QNC_PCIE_SVID
) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1
, PCI_VENDOR_ID_OFFSET
);
885 // Set the IPF bit in MCR2
887 QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_MPC2
) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_MPC2
, B_QNC_PCIE_MPC2_IPF
);
888 QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1
, R_QNC_PCIE_MPC2
) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1
, R_QNC_PCIE_MPC2
, B_QNC_PCIE_MPC2_IPF
);
891 // Set up the Posted and Non Posted Request sizes for PCIe
893 QNCMmPci32(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_CCFG
) = QNCMmPci32AndThenOr(0, PCI_BUS_NUMBER_QNC
, PCI_DEVICE_NUMBER_PCIE_ROOTPORT
, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0
, R_QNC_PCIE_CCFG
, ~B_QNC_PCIE_CCFG_UPSD
, (B_QNC_PCIE_CCFG_UNRS
| B_QNC_PCIE_CCFG_UPRS
));
900 Complete initialization all the pci express rootports on Soc.
907 UINT64 PciExpressBar
;
908 UINT32 QNCRootComplexBar
;
913 PCIEXP_ROOT_PORT_CONFIGURATION
*mRootPortConfig
;
914 QNC_DEVICE_ENABLES mQNCDeviceEnables
;
919 QNCRootComplexBar
= QNC_RCRB_BASE
;
920 QNCGpioBase
= LpcPciCfg32 (R_QNC_LPC_GBA_BASE
) & B_QNC_LPC_GPA_BASE_MASK
;
921 QNCPmioBase
= LpcPciCfg32 (R_QNC_LPC_PM1BLK
) & B_QNC_LPC_PM1BLK_MASK
;
922 QNCGpeBase
= LpcPciCfg32 (R_QNC_LPC_GPE0BLK
) & B_QNC_LPC_GPE0BLK_MASK
;
923 RpEnableMask
= 0; // assume all root ports are disabled
925 PciExpressBar
= PcdGet64 (PcdPciExpressBaseAddress
);
928 // Get platform information from PCD entries
930 mQNCDeviceEnables
.Uint32
= PcdGet32 (PcdDeviceEnables
);
931 mRootPortConfig
= (PCIEXP_ROOT_PORT_CONFIGURATION
*) PcdGetPtr (PcdPcieRootPortConfiguration
);
933 DEBUG ((EFI_D_INFO
, " mRootPortConfig: 0x%x, value1: 0x%x, value2: 0x%x, value3: 0x%x, value4: 0x%x\n",
934 mRootPortConfig
, mRootPortConfig
[0].Uint32
, mRootPortConfig
[1].Uint32
,
935 mRootPortConfig
[2].Uint32
, mRootPortConfig
[3].Uint32
));
937 QNCDownStreamPortsInit (