]>
Commit | Line | Data |
---|---|---|
4595449b OM |
1 | /** @file\r |
2 | * Initialize the XPress-RICH3 PCIe Root complex\r | |
3 | *\r | |
4 | * Copyright (c) 2011-2015, ARM Ltd. All rights reserved.\r | |
5 | *\r | |
6 | * This program and the accompanying materials\r | |
7 | * are licensed and made available under the terms and conditions of the BSD License\r | |
8 | * which accompanies this distribution. The full text of the license may be found at\r | |
9 | * http://opensource.org/licenses/bsd-license.php\r | |
10 | *\r | |
11 | * THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
12 | * WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
13 | *\r | |
14 | **/\r | |
15 | \r | |
16 | #include "PciHostBridge.h"\r | |
17 | \r | |
18 | #include <Protocol/Cpu.h>\r | |
19 | \r | |
20 | #include "ArmPlatform.h"\r | |
21 | \r | |
22 | EFI_CPU_ARCH_PROTOCOL *mCpu;\r | |
23 | \r | |
24 | #define PCI_BRIDGE_REVISION_ID 1\r | |
25 | #define CLASS_CODE_REGISTER(Class, SubClass, ProgIf) ((Class << 16) | (SubClass << 8) | ProgIf)\r | |
26 | #define PLDA_BRIDGE_CCR CLASS_CODE_REGISTER(PCI_CLASS_BRIDGE, \\r | |
27 | PCI_CLASS_BRIDGE_P2P, \\r | |
28 | PCI_IF_BRIDGE_P2P)\r | |
29 | \r | |
30 | STATIC\r | |
31 | VOID\r | |
32 | SetTranslationAddressEntry (\r | |
33 | IN EFI_CPU_IO2_PROTOCOL *CpuIo,\r | |
34 | IN UINTN Entry,\r | |
35 | IN UINT64 SourceAddress,\r | |
36 | IN UINT64 TranslatedAddress,\r | |
37 | IN UINT64 TranslationSize,\r | |
38 | IN UINT64 TranslationParameter\r | |
39 | )\r | |
40 | {\r | |
41 | UINTN Log2Size = HighBitSet64 (TranslationSize);\r | |
42 | \r | |
43 | // Ensure the size is a power of two. Restriction form the AXI Translation logic\r | |
44 | // Othwerwise we increase the translation size\r | |
45 | if (TranslationSize != (1ULL << Log2Size)) {\r | |
46 | DEBUG ((EFI_D_WARN, "PCI: The size 0x%lX of the region 0x%lx has been increased to "\r | |
47 | "be a power of two for the AXI translation table.\n",\r | |
48 | TranslationSize, SourceAddress));\r | |
49 | Log2Size++;\r | |
50 | }\r | |
51 | \r | |
52 | PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_SRC_ADDR_LOW_SIZE,\r | |
53 | (UINT32)SourceAddress | ((Log2Size - 1) << 1) | 0x1);\r | |
54 | PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_SRC_ADDR_HI, SourceAddress >> 32);\r | |
55 | \r | |
56 | PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_LOW, (UINT32)TranslatedAddress);\r | |
57 | PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_HI, TranslatedAddress >> 32);\r | |
58 | \r | |
59 | PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_PARAM, TranslationParameter);\r | |
60 | }\r | |
61 | \r | |
62 | EFI_STATUS\r | |
63 | HWPciRbInit (\r | |
64 | IN EFI_CPU_IO2_PROTOCOL *CpuIo\r | |
65 | )\r | |
66 | {\r | |
67 | UINT32 Value;\r | |
68 | UINT32 Index;\r | |
69 | UINTN TranslationTable;\r | |
70 | \r | |
71 | PCI_TRACE ("VExpressPciRbInit()");\r | |
72 | \r | |
73 | PCI_TRACE ("PCIe Setting up Address Translation");\r | |
74 | \r | |
162e7891 JL |
75 | // The Juno PIO window is 8M, so we need full 32-bit PIO decoding.\r |
76 | PCIE_ROOTPORT_WRITE32 (PCIE_BAR_WIN, PCIE_BAR_WIN_SUPPORT_IO | PCIE_BAR_WIN_SUPPORT_IO32 |\r | |
77 | PCIE_BAR_WIN_SUPPORT_MEM | PCIE_BAR_WIN_SUPPORT_MEM64);\r | |
4595449b OM |
78 | \r |
79 | // Setup the PCI Configuration Registers\r | |
80 | // Offset 0a: SubClass 04 PCI-PCI Bridge\r | |
81 | // Offset 0b: BaseClass 06 Bridge Device\r | |
82 | // The Class Code register is a 24 bit and can be configured by setting up the PCIE_PCI_IDS\r | |
83 | // Refer [1] Chapter 13\r | |
84 | PCIE_ROOTPORT_WRITE32 (PCIE_PCI_IDS + PCIE_PCI_IDS_CLASSCODE_OFFSET, ((PLDA_BRIDGE_CCR << 8) | PCI_BRIDGE_REVISION_ID));\r | |
85 | \r | |
86 | //\r | |
87 | // PCIE Window 0 -> AXI4 Slave 0 Address Translations\r | |
88 | //\r | |
89 | TranslationTable = VEXPRESS_ATR_PCIE_WIN0;\r | |
90 | \r | |
91 | // MSI Support\r | |
92 | SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_GIV2M_MSI_BASE, ARM_JUNO_GIV2M_MSI_BASE,\r | |
93 | ARM_JUNO_GIV2M_MSI_SZ, PCI_ATR_TRSLID_AXIDEVICE);\r | |
94 | TranslationTable += PCI_ATR_ENTRY_SIZE;\r | |
95 | \r | |
96 | // System Memory Support\r | |
97 | SetTranslationAddressEntry (CpuIo, TranslationTable, PcdGet64 (PcdSystemMemoryBase), PcdGet64 (PcdSystemMemoryBase),\r | |
98 | PcdGet64 (PcdSystemMemorySize), PCI_ATR_TRSLID_AXIMEMORY);\r | |
99 | TranslationTable += PCI_ATR_ENTRY_SIZE;\r | |
100 | SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE,\r | |
101 | ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ, PCI_ATR_TRSLID_AXIMEMORY);\r | |
102 | \r | |
103 | //\r | |
104 | // PCIE Window 0 -> AXI4 Slave 0 Address Translations\r | |
105 | //\r | |
106 | TranslationTable = VEXPRESS_ATR_AXI4_SLV1;\r | |
107 | \r | |
108 | // PCI ECAM Support\r | |
109 | SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_ECAM_BASE, PCI_ECAM_BASE, PCI_ECAM_SIZE, PCI_ATR_TRSLID_PCIE_CONF);\r | |
110 | TranslationTable += PCI_ATR_ENTRY_SIZE;\r | |
111 | \r | |
162e7891 JL |
112 | // PCI IO Support, the PIO space is translated from the arm MMIO PCI_IO_BASE address to the PIO base address of 0\r |
113 | // AKA, PIO addresses used by endpoints are generally in the range of 0-64K.\r | |
114 | SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_IO_BASE, 0, PCI_IO_SIZE, PCI_ATR_TRSLID_PCIE_IO);\r | |
4595449b OM |
115 | TranslationTable += PCI_ATR_ENTRY_SIZE;\r |
116 | \r | |
117 | // PCI MEM32 Support\r | |
118 | SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM32_BASE, PCI_MEM32_BASE, PCI_MEM32_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);\r | |
119 | TranslationTable += PCI_ATR_ENTRY_SIZE;\r | |
120 | \r | |
121 | // PCI MEM64 Support\r | |
122 | SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM64_BASE, PCI_MEM64_BASE, PCI_MEM64_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);\r | |
123 | \r | |
124 | // Add credits\r | |
125 | PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED, 0x00f0b818);\r | |
126 | PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED + 4, 0x1);\r | |
127 | \r | |
128 | // Allow ECRC\r | |
129 | PCIE_ROOTPORT_WRITE32 (PCIE_PEX_SPC2, 0x6006);\r | |
130 | \r | |
131 | // Reset controller\r | |
132 | PCIE_CONTROL_WRITE32 (PCIE_CONTROL_RST_CTL, PCIE_CONTROL_RST_CTL_RCPHY_REL);\r | |
133 | \r | |
134 | // Wait for reset\r | |
135 | for (Index = 0; Index < 1000; Index++) {\r | |
136 | gBS->Stall (1000);\r | |
137 | PCIE_CONTROL_READ32 (PCIE_CONTROL_RST_STS, Value);\r | |
138 | if ((Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) == PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) {\r | |
139 | break;\r | |
140 | }\r | |
141 | }\r | |
142 | \r | |
143 | // Check for reset\r | |
144 | if (!(Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT)) {\r | |
145 | DEBUG ((EFI_D_ERROR, "PCIe failed to come out of reset: %x.\n", Value));\r | |
146 | return EFI_NOT_READY;\r | |
147 | }\r | |
148 | \r | |
149 | gBS->Stall (1000);\r | |
150 | PCI_TRACE ("Checking link Status...");\r | |
151 | \r | |
152 | // Wait for Link Up\r | |
153 | for (Index = 0; Index < 1000; Index++) {\r | |
154 | gBS->Stall (1000);\r | |
155 | PCIE_ROOTPORT_READ32 (VEXPRESS_BASIC_STATUS, Value);\r | |
156 | if (Value & LINK_UP) {\r | |
157 | break;\r | |
158 | }\r | |
159 | }\r | |
160 | \r | |
161 | // Check for link up\r | |
162 | if (!(Value & LINK_UP)) {\r | |
163 | DEBUG ((EFI_D_ERROR, "PCIe link not up: %x.\n", Value));\r | |
164 | return EFI_NOT_READY;\r | |
165 | }\r | |
166 | \r | |
167 | PCIE_ROOTPORT_WRITE32 (PCIE_IMASK_LOCAL, PCIE_INT_MSI | PCIE_INT_INTx);\r | |
168 | \r | |
169 | return EFI_SUCCESS;\r | |
170 | }\r |