• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
SetTranslationAddressEntry(IN EFI_CPU_IO2_PROTOCOL * CpuIo,IN UINTN Entry,IN UINT64 SourceAddress,IN UINT64 TranslatedAddress,IN UINT64 TranslationSize,IN UINT64 TranslationParameter)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
HWPciRbInit(IN EFI_CPU_IO2_PROTOCOL * CpuIo)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   PCIE_ROOTPORT_WRITE32 (PCIE_BAR_WIN, PCIE_BAR_WIN_SUPPORT_IO | PCIE_BAR_WIN_SUPPORT_MEM | PCIE_BAR_WIN_SUPPORT_MEM64);
76 
77   // Setup the PCI Configuration Registers
78   // Offset 0a: SubClass       04 PCI-PCI Bridge
79   // Offset 0b: BaseClass      06 Bridge Device
80   // The Class Code register is a 24 bit and can be configured by setting up the PCIE_PCI_IDS
81   // Refer [1] Chapter 13
82   PCIE_ROOTPORT_WRITE32 (PCIE_PCI_IDS + PCIE_PCI_IDS_CLASSCODE_OFFSET, ((PLDA_BRIDGE_CCR << 8) | PCI_BRIDGE_REVISION_ID));
83 
84   //
85   // PCIE Window 0 -> AXI4 Slave 0 Address Translations
86   //
87   TranslationTable = VEXPRESS_ATR_PCIE_WIN0;
88 
89   // MSI Support
90   SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_GIV2M_MSI_BASE, ARM_JUNO_GIV2M_MSI_BASE,
91       ARM_JUNO_GIV2M_MSI_SZ, PCI_ATR_TRSLID_AXIDEVICE);
92   TranslationTable += PCI_ATR_ENTRY_SIZE;
93 
94   // System Memory Support
95   SetTranslationAddressEntry (CpuIo, TranslationTable, PcdGet64 (PcdSystemMemoryBase), PcdGet64 (PcdSystemMemoryBase),
96       PcdGet64 (PcdSystemMemorySize), PCI_ATR_TRSLID_AXIMEMORY);
97   TranslationTable += PCI_ATR_ENTRY_SIZE;
98   SetTranslationAddressEntry (CpuIo, TranslationTable, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE, ARM_JUNO_EXTRA_SYSTEM_MEMORY_BASE,
99       ARM_JUNO_EXTRA_SYSTEM_MEMORY_SZ, PCI_ATR_TRSLID_AXIMEMORY);
100 
101   //
102   // PCIE Window 0 -> AXI4 Slave 0 Address Translations
103   //
104   TranslationTable = VEXPRESS_ATR_AXI4_SLV1;
105 
106   // PCI ECAM Support
107   SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_ECAM_BASE, PCI_ECAM_BASE, PCI_ECAM_SIZE, PCI_ATR_TRSLID_PCIE_CONF);
108   TranslationTable += PCI_ATR_ENTRY_SIZE;
109 
110   // PCI IO Support
111   SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_IO_BASE, PCI_IO_BASE, PCI_IO_SIZE, PCI_ATR_TRSLID_PCIE_IO);
112   TranslationTable += PCI_ATR_ENTRY_SIZE;
113 
114   // PCI MEM32 Support
115   SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM32_BASE, PCI_MEM32_BASE, PCI_MEM32_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
116   TranslationTable += PCI_ATR_ENTRY_SIZE;
117 
118   // PCI MEM64 Support
119   SetTranslationAddressEntry (CpuIo, TranslationTable, PCI_MEM64_BASE, PCI_MEM64_BASE, PCI_MEM64_SIZE, PCI_ATR_TRSLID_PCIE_MEMORY);
120 
121   // Add credits
122   PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED, 0x00f0b818);
123   PCIE_ROOTPORT_WRITE32 (PCIE_VC_CRED + 4, 0x1);
124 
125   // Allow ECRC
126   PCIE_ROOTPORT_WRITE32 (PCIE_PEX_SPC2, 0x6006);
127 
128   // Reset controller
129   PCIE_CONTROL_WRITE32 (PCIE_CONTROL_RST_CTL, PCIE_CONTROL_RST_CTL_RCPHY_REL);
130 
131   // Wait for reset
132   for (Index = 0; Index < 1000; Index++) {
133     gBS->Stall (1000);
134     PCIE_CONTROL_READ32 (PCIE_CONTROL_RST_STS, Value);
135     if ((Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) == PCIE_CONTROL_RST_STS_RCPHYPLL_OUT) {
136       break;
137     }
138   }
139 
140   // Check for reset
141   if (!(Value & PCIE_CONTROL_RST_STS_RCPHYPLL_OUT)) {
142     DEBUG ((EFI_D_ERROR, "PCIe failed to come out of reset: %x.\n", Value));
143     return EFI_NOT_READY;
144   }
145 
146   gBS->Stall (1000);
147   PCI_TRACE ("Checking link Status...");
148 
149   // Wait for Link Up
150   for (Index = 0; Index < 1000; Index++) {
151     gBS->Stall (1000);
152     PCIE_ROOTPORT_READ32 (VEXPRESS_BASIC_STATUS, Value);
153     if (Value & LINK_UP) {
154       break;
155     }
156   }
157 
158   // Check for link up
159   if (!(Value & LINK_UP)) {
160     DEBUG ((EFI_D_ERROR, "PCIe link not up: %x.\n", Value));
161     return EFI_NOT_READY;
162   }
163 
164   PCIE_ROOTPORT_WRITE32 (PCIE_IMASK_LOCAL, PCIE_INT_MSI | PCIE_INT_INTx);
165 
166   return EFI_SUCCESS;
167 }
168