]> git.proxmox.com Git - mirror_edk2.git/blob - ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/XPressRich3.c
ArmPlatformPkg/ArmJuno: fix Juno PIO host bridge mapping
[mirror_edk2.git] / ArmPlatformPkg / ArmJunoPkg / Drivers / PciHostBridgeDxe / XPressRich3.c
1 /** @file
2 * Initialize the XPress-RICH3 PCIe Root complex
3 *
4 * Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
5 *
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
10 *
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.
13 *
14 **/
15
16 #include "PciHostBridge.h"
17
18 #include <Protocol/Cpu.h>
19
20 #include "ArmPlatform.h"
21
22 EFI_CPU_ARCH_PROTOCOL *mCpu;
23
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, \
28 PCI_IF_BRIDGE_P2P)
29
30 STATIC
31 VOID
32 SetTranslationAddressEntry (
33 IN EFI_CPU_IO2_PROTOCOL *CpuIo,
34 IN UINTN Entry,
35 IN UINT64 SourceAddress,
36 IN UINT64 TranslatedAddress,
37 IN UINT64 TranslationSize,
38 IN UINT64 TranslationParameter
39 )
40 {
41 UINTN Log2Size = HighBitSet64 (TranslationSize);
42
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));
49 Log2Size++;
50 }
51
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);
55
56 PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_LOW, (UINT32)TranslatedAddress);
57 PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_ADDR_HI, TranslatedAddress >> 32);
58
59 PCIE_ROOTPORT_WRITE32 (Entry + PCI_ATR_TRSL_PARAM, TranslationParameter);
60 }
61
62 EFI_STATUS
63 HWPciRbInit (
64 IN EFI_CPU_IO2_PROTOCOL *CpuIo
65 )
66 {
67 UINT32 Value;
68 UINT32 Index;
69 UINTN TranslationTable;
70
71 PCI_TRACE ("VExpressPciRbInit()");
72
73 PCI_TRACE ("PCIe Setting up Address Translation");
74
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);
78
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));
85
86 //
87 // PCIE Window 0 -> AXI4 Slave 0 Address Translations
88 //
89 TranslationTable = VEXPRESS_ATR_PCIE_WIN0;
90
91 // MSI Support
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;
95
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);
102
103 //
104 // PCIE Window 0 -> AXI4 Slave 0 Address Translations
105 //
106 TranslationTable = VEXPRESS_ATR_AXI4_SLV1;
107
108 // PCI ECAM Support
109 SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_ECAM_BASE, PCI_ECAM_BASE, PCI_ECAM_SIZE, PCI_ATR_TRSLID_PCIE_CONF);
110 TranslationTable += PCI_ATR_ENTRY_SIZE;
111
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;
116
117 // PCI MEM32 Support
118 SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM32_BASE, PCI_MEM32_BASE, PCI_MEM32_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
119 TranslationTable += PCI_ATR_ENTRY_SIZE;
120
121 // PCI MEM64 Support
122 SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM64_BASE, PCI_MEM64_BASE, PCI_MEM64_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
123
124 // Add credits
125 PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED, 0x00f0b818);
126 PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED + 4, 0x1);
127
128 // Allow ECRC
129 PCIE_ROOTPORT_WRITE32 (PCIE_PEX_SPC2, 0x6006);
130
131 // Reset controller
132 PCIE_CONTROL_WRITE32 (PCIE_CONTROL_RST_CTL, PCIE_CONTROL_RST_CTL_RCPHY_REL);
133
134 // Wait for reset
135 for (Index = 0; Index < 1000; Index++) {
136 gBS->Stall (1000);
137 PCIE_CONTROL_READ32 (PCIE_CONTROL_RST_STS, Value);
138 if ((Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) == PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) {
139 break;
140 }
141 }
142
143 // Check for reset
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;
147 }
148
149 gBS->Stall (1000);
150 PCI_TRACE ("Checking link Status...");
151
152 // Wait for Link Up
153 for (Index = 0; Index < 1000; Index++) {
154 gBS->Stall (1000);
155 PCIE_ROOTPORT_READ32 (VEXPRESS_BASIC_STATUS, Value);
156 if (Value & LINK_UP) {
157 break;
158 }
159 }
160
161 // Check for link up
162 if (!(Value & LINK_UP)) {
163 DEBUG ((EFI_D_ERROR, "PCIe link not up: %x.\n", Value));
164 return EFI_NOT_READY;
165 }
166
167 PCIE_ROOTPORT_WRITE32 (PCIE_IMASK_LOCAL, PCIE_INT_MSI | PCIE_INT_INTx);
168
169 return EFI_SUCCESS;
170 }