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 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