2 * Initialize the XPress-RICH3 PCIe Root complex
4 * Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
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 "PciHostBridge.h"
18 #include <Protocol/Cpu.h>
20 #include "ArmPlatform.h"
22 EFI_CPU_ARCH_PROTOCOL
*mCpu
;
24 #define PCI_BRIDGE_REVISION_ID 1
25 #define CLASS_CODE_REGISTER(Class, SubClass, ProgIf) ((Class << 16) | (SubClass << 8) | ProgIf)
26 #define PLDA_BRIDGE_CCR CLASS_CODE_REGISTER(PCI_CLASS_BRIDGE, \
27 PCI_CLASS_BRIDGE_P2P, \
32 SetTranslationAddressEntry (
33 IN EFI_CPU_IO2_PROTOCOL
*CpuIo
,
35 IN UINT64 SourceAddress
,
36 IN UINT64 TranslatedAddress
,
37 IN UINT64 TranslationSize
,
38 IN UINT64 TranslationParameter
41 UINTN Log2Size
= HighBitSet64 (TranslationSize
);
43 // Ensure the size is a power of two. Restriction form the AXI Translation logic
44 // Othwerwise we increase the translation size
45 if (TranslationSize
!= (1ULL << Log2Size
)) {
46 DEBUG ((EFI_D_WARN
, "PCI: The size 0x%lX of the region 0x%lx has been increased to "
47 "be a power of two for the AXI translation table.\n",
48 TranslationSize
, SourceAddress
));
52 PCIE_ROOTPORT_WRITE32 (Entry
+ PCI_ATR_SRC_ADDR_LOW_SIZE
,
53 (UINT32
)SourceAddress
| ((Log2Size
- 1) << 1) | 0x1);
54 PCIE_ROOTPORT_WRITE32 (Entry
+ PCI_ATR_SRC_ADDR_HI
, SourceAddress
>> 32);
56 PCIE_ROOTPORT_WRITE32 (Entry
+ PCI_ATR_TRSL_ADDR_LOW
, (UINT32
)TranslatedAddress
);
57 PCIE_ROOTPORT_WRITE32 (Entry
+ PCI_ATR_TRSL_ADDR_HI
, TranslatedAddress
>> 32);
59 PCIE_ROOTPORT_WRITE32 (Entry
+ PCI_ATR_TRSL_PARAM
, TranslationParameter
);
64 IN EFI_CPU_IO2_PROTOCOL
*CpuIo
69 UINTN TranslationTable
;
71 PCI_TRACE ("VExpressPciRbInit()");
73 PCI_TRACE ("PCIe Setting up Address Translation");
75 // The Juno PIO window is 8M, so we need full 32-bit PIO decoding.
76 PCIE_ROOTPORT_WRITE32 (PCIE_BAR_WIN
, PCIE_BAR_WIN_SUPPORT_IO
| PCIE_BAR_WIN_SUPPORT_IO32
|
77 PCIE_BAR_WIN_SUPPORT_MEM
| PCIE_BAR_WIN_SUPPORT_MEM64
);
79 // Setup the PCI Configuration Registers
80 // Offset 0a: SubClass 04 PCI-PCI Bridge
81 // Offset 0b: BaseClass 06 Bridge Device
82 // The Class Code register is a 24 bit and can be configured by setting up the PCIE_PCI_IDS
83 // Refer [1] Chapter 13
84 PCIE_ROOTPORT_WRITE32 (PCIE_PCI_IDS
+ PCIE_PCI_IDS_CLASSCODE_OFFSET
, ((PLDA_BRIDGE_CCR
<< 8) | PCI_BRIDGE_REVISION_ID
));
87 // PCIE Window 0 -> AXI4 Slave 0 Address Translations
89 TranslationTable
= VEXPRESS_ATR_PCIE_WIN0
;
92 SetTranslationAddressEntry (CpuIo
, TranslationTable
, ARM_JUNO_GIV2M_MSI_BASE
, ARM_JUNO_GIV2M_MSI_BASE
,
93 ARM_JUNO_GIV2M_MSI_SZ
, PCI_ATR_TRSLID_AXIDEVICE
);
94 TranslationTable
+= PCI_ATR_ENTRY_SIZE
;
96 // System Memory Support
97 SetTranslationAddressEntry (CpuIo
, TranslationTable
, PcdGet64 (PcdSystemMemoryBase
), PcdGet64 (PcdSystemMemoryBase
),
98 PcdGet64 (PcdSystemMemorySize
), PCI_ATR_TRSLID_AXIMEMORY
);
99 TranslationTable
+= PCI_ATR_ENTRY_SIZE
;
100 SetTranslationAddressEntry (CpuIo
, TranslationTable
, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE
, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE
,
101 ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ
, PCI_ATR_TRSLID_AXIMEMORY
);
104 // PCIE Window 0 -> AXI4 Slave 0 Address Translations
106 TranslationTable
= VEXPRESS_ATR_AXI4_SLV1
;
109 SetTranslationAddressEntry (CpuIo
, TranslationTable
, PCI_ECAM_BASE
, PCI_ECAM_BASE
, PCI_ECAM_SIZE
, PCI_ATR_TRSLID_PCIE_CONF
);
110 TranslationTable
+= PCI_ATR_ENTRY_SIZE
;
112 // PCI IO Support, the PIO space is translated from the arm MMIO PCI_IO_BASE address to the PIO base address of 0
113 // AKA, PIO addresses used by endpoints are generally in the range of 0-64K.
114 SetTranslationAddressEntry (CpuIo
, TranslationTable
, PCI_IO_BASE
, 0, PCI_IO_SIZE
, PCI_ATR_TRSLID_PCIE_IO
);
115 TranslationTable
+= PCI_ATR_ENTRY_SIZE
;
118 SetTranslationAddressEntry (CpuIo
, TranslationTable
, PCI_MEM32_BASE
, PCI_MEM32_BASE
, PCI_MEM32_SIZE
, PCI_ATR_TRSLID_PCIE_MEMORY
);
119 TranslationTable
+= PCI_ATR_ENTRY_SIZE
;
122 SetTranslationAddressEntry (CpuIo
, TranslationTable
, PCI_MEM64_BASE
, PCI_MEM64_BASE
, PCI_MEM64_SIZE
, PCI_ATR_TRSLID_PCIE_MEMORY
);
125 PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED
, 0x00f0b818);
126 PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED
+ 4, 0x1);
129 PCIE_ROOTPORT_WRITE32 (PCIE_PEX_SPC2
, 0x6006);
132 PCIE_CONTROL_WRITE32 (PCIE_CONTROL_RST_CTL
, PCIE_CONTROL_RST_CTL_RCPHY_REL
);
135 for (Index
= 0; Index
< 1000; Index
++) {
137 PCIE_CONTROL_READ32 (PCIE_CONTROL_RST_STS
, Value
);
138 if ((Value
& PCIE_CONTROL_RST_STS_RCPHYPLL_OUT
) == PCIE_CONTROL_RST_STS_RCPHYPLL_OUT
) {
144 if (!(Value
& PCIE_CONTROL_RST_STS_RCPHYPLL_OUT
)) {
145 DEBUG ((EFI_D_ERROR
, "PCIe failed to come out of reset: %x.\n", Value
));
146 return EFI_NOT_READY
;
150 PCI_TRACE ("Checking link Status...");
153 for (Index
= 0; Index
< 1000; Index
++) {
155 PCIE_ROOTPORT_READ32 (VEXPRESS_BASIC_STATUS
, Value
);
156 if (Value
& LINK_UP
) {
162 if (!(Value
& LINK_UP
)) {
163 DEBUG ((EFI_D_ERROR
, "PCIe link not up: %x.\n", Value
));
164 return EFI_NOT_READY
;
167 PCIE_ROOTPORT_WRITE32 (PCIE_IMASK_LOCAL
, PCIE_INT_MSI
| PCIE_INT_INTx
);