* [PATCH edk2-platforms 1/3] Platform/NXP : Add PCI Host Bridge Libary
2017-12-21 18:48 [PATCH edk2-platforms 0/3] Platform/NXP-Added NXP PCI Host Bridge Driver Vabhav
@ 2017-12-21 18:48 ` Vabhav
2017-12-21 18:48 ` [PATCH edk2-platforms 2/3] Platform/NXP : Add PCI Host Bridge Driver Vabhav
` (2 subsequent siblings)
3 siblings, 0 replies; 7+ messages in thread
From: Vabhav @ 2017-12-21 18:48 UTC (permalink / raw)
To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel
Added PCIe Host Bridge Library to provide helper
functions which will be used by PCIe Host bridge Dxe
Driver
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
Platform/NXP/Include/PciCntrlLib.h | 323 +++++++++++
Platform/NXP/Include/PciLib.h | 414 ++++++++++++++
Platform/NXP/Library/PciHostBridgeLib/PciCntrl.c | 628 +++++++++++++++++++++
.../Library/PciHostBridgeLib/PciHostBridgeLib.inf | 49 ++
Platform/NXP/Library/PciHostBridgeLib/PciRbLib.c | 331 +++++++++++
5 files changed, 1745 insertions(+)
create mode 100644 Platform/NXP/Include/PciCntrlLib.h
create mode 100644 Platform/NXP/Include/PciLib.h
create mode 100644 Platform/NXP/Library/PciHostBridgeLib/PciCntrl.c
create mode 100644 Platform/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
create mode 100644 Platform/NXP/Library/PciHostBridgeLib/PciRbLib.c
diff --git a/Platform/NXP/Include/PciCntrlLib.h b/Platform/NXP/Include/PciCntrlLib.h
new file mode 100644
index 0000000..c8001d9
--- /dev/null
+++ b/Platform/NXP/Include/PciCntrlLib.h
@@ -0,0 +1,323 @@
+/** PciCntrlLib.c
+ The Header file of the Pci Controller Driver
+
+ Some part of code is inspired from EDK II, file:
+ MdePkg/Include/Library/PciLib.h
+
+ Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI_CNTRL_H_
+#define _PCI_CNTRL_H_
+
+#include <PciRootBridge.h>
+#include <PciLib.h>
+
+#define SDRAM_BASE 0x80000000
+
+// LUT registers
+#define LS_PCIE_LUT_BASE PcdGet64 (PcdPcieLutBase)
+#define LS_PCIE_LUT_DBG PcdGet64 (PcdPcieLutDbg)
+#define PCIE_LUT_UDR(n) (0x800 + (n) * 8)
+#define PCIE_LUT_LDR(n) (0x804 + (n) * 8)
+#define PCIE_LUT_ENABLE (1 << 31)
+
+#ifndef LS_PCI_MEMORY_BUS
+#define LS_PCI_MEMORY_BUS SDRAM_BASE
+#endif
+
+#ifndef LS_PCI_MEMORY_PHYS
+#define LS_PCI_MEMORY_PHYS SDRAM_BASE
+#endif
+
+#ifndef LS_PCI_MEMORY_SIZE
+#define LS_PCI_MEMORY_SIZE (2 * 1024 * 1024 * 1024UL)
+#endif
+
+/* iATU registers */
+#define LS_PCIE_ATU_VIEWPORT 0x900
+#define LS_PCIE_ATU_REGION_INBOUND (0x1 << 31)
+#define LS_PCIE_ATU_REGION_OUTBOUND (0x0 << 31)
+#define LS_PCIE_ATU_REGION_INDEX0 (0x0 << 0)
+#define LS_PCIE_ATU_REGION_INDEX1 (0x1 << 0)
+#define LS_PCIE_ATU_REGION_INDEX2 (0x2 << 0)
+#define LS_PCIE_ATU_REGION_INDEX3 (0x3 << 0)
+#define LS_PCIE_ATU_REGION_INDEX4 (0x4 << 0)
+#define LS_PCIE_ATU_CR1 0x904
+#define LS_PCIE_ATU_TYPE_MEM (0x0 << 0)
+#define LS_PCIE_ATU_TYPE_IO (0x2 << 0)
+#define LS_PCIE_ATU_TYPE_CFG0 (0x4 << 0)
+#define LS_PCIE_ATU_TYPE_CFG1 (0x5 << 0)
+#define LS_PCIE_ATU_CR2 0x908
+#define LS_PCIE_ATU_ENABLE (0x1 << 31)
+#define LS_PCIE_ATU_BAR_MODE_ENABLE (0x1 << 30)
+#define LS_PCIE_ATU_LOWER_BASE 0x90C
+#define LS_PCIE_ATU_UPPER_BASE 0x910
+#define LS_PCIE_ATU_LIMIT 0x914
+#define LS_PCIE_ATU_LOWER_TARGET 0x918
+#define LS_PCIE_ATU_BUS(x) (((x) & 0xff) << 24)
+#define LS_PCIE_ATU_DEV(x) (((x) & 0x1f) << 19)
+#define LS_PCIE_ATU_FUNC(x) (((x) & 0x7) << 16)
+#define LS_PCIE_ATU_UPPER_TARGET 0x91C
+
+/** DBI Read-Only Write Enable Register: Pg 1518 RM rev B
+ Set bit 0 of this register as 1.
+ Write to RO Registers Using DBI.
+ When you set this field to "1", then some RO and HwInit bits are writable
+ from the local application through the DBI.
+ **/
+#define LS_PCIE_DBI_RO_WR_EN 0x8bc
+
+#define LS_PCIE_LINK_CAP 0x7c
+#define LS_PCIE_LINK_SPEED_MASK 0xf
+#define LS_PCIE_LINK_STA 0x82
+
+#define LS_LTSSM_STATE_MASK 0x3f
+#define LS_LTSSM_PCIE_L0 0x11 // L0 state
+
+#define LS_PCIE_DBI_SIZE 0x100000 // 1M
+
+#define PCI_CLASS_REVISION 0x08 // High 24 bits are class,low 8 revision
+#define PCI_REVISION_ID 0x08 // Revision ID
+#define PCI_CLASS_PROG 0x09 // Reg. Level Programming Interface
+#define PCI_CLASS_DEVICE 0x0a // Device class
+#define PCI_CLASS_CODE 0x0b // Device class code
+#define PCI_CLASS_BRIDGE_PCI 0x0604
+
+/**
+ Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an
+ address that can be passed to the PCI Library functions.
+
+ @param Bus PCI Bus number. Range 0..255.
+ @param Device PCI Device number. Range 0..31.
+ @param Function PCI Function number. Range 0..7.
+ @param Register PCI Register number. Range 0..255 for PCI. Range 0..4095
+ for PCI Express.
+
+ @return The encoded PCI address.
+ **/
+#define PCI_LIB_ADDRESS(Bus,Device,Function,Register) \
+ (((Register) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20))
+
+#define PCI_BUS_DEV(Bus,Device,Function) \
+ ((((Function) & 0x07) << 16) | (((Device) & 0x1f) << 19) | (((Bus) & 0xff) << 24))
+
+/**
+ Function to set-up PCIe region
+**/
+VOID
+PciSetRegion (
+ IN PciRegion *Reg,
+ IN PciAddrT BusStart,
+ IN PhysAddrT PhysStart,
+ IN PciSizeT Size,
+ IN UINTN Flags
+);
+
+/**
+ Function to setup PCIe space(Mem,I/O,Configuration)
+**/
+VOID
+SetLSPcieInfo (
+ IN LsPcieInfo *PcieInfo,
+ IN UINTN Num
+);
+
+/**
+ Function to check PCIe link state
+**/
+INTN
+PcieLinkState (
+ IN LsPcie *Pcie
+);
+
+/**
+ Helper Function to check PCIe link state
+ Downgrade the speed to gen1
+**/
+INTN
+PcieLinkUp (
+ IN LsPcie *pcie
+);
+
+/**
+ Function to set up PCIe (cfg0)configuration space
+**/
+VOID
+PcieCfg0SetBusdev (
+ IN LsPcie *Pcie,
+ IN UINT32 BusDev
+);
+
+/**
+ Function to set up PCIe (cfg1)configuration space
+**/
+VOID
+PcieCfg1SetBusdev (
+ IN LsPcie *Pcie,
+ IN UINT32 BusDev
+);
+
+/**
+ Function to set up iATU for outbound PCIe transactions
+**/
+VOID
+PcieIatuOutboundSet (
+ IN LsPcie *Pcie,
+ IN UINT32 Idx,
+ IN UINT32 Type,
+ IN UINT64 Phys,
+ IN UINT64 BusAddr,
+ IN UINT64 Size
+);
+
+EFI_STATUS
+PciSkipDev (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev
+);
+
+/**
+ Function to verify if PCIe address space is valid
+**/
+EFI_STATUS
+PcieAddrValid (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev
+);
+
+/**
+ Function to read value(32-bit) from PCI space
+**/
+EFI_STATUS
+PcieReadConfig (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Where,
+ IN OUT UINT32 *Val
+);
+
+/**
+ Function to read byte from PCI space
+**/
+EFI_STATUS
+PcieReadConfigByte (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ IN OUT UINT8 *Val
+);
+
+/**
+ Function to read word from PCI space
+**/
+EFI_STATUS
+PcieReadConfigWord (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ IN OUT UINT16 *Val
+);
+
+/**
+ Function to write byte in PCI space
+**/
+EFI_STATUS
+PcieWriteConfigByte (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ OUT UINT8 Val
+);
+
+/**
+ Function to write word in PCI space
+**/
+EFI_STATUS
+PcieWriteConfigWord (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ OUT UINT16 Val
+);
+
+/**
+ Function to write value(32-bit) in PCI space
+**/
+EFI_STATUS
+PcieWriteConfig (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Where,
+ IN UINT32 Val
+);
+
+/**
+ Function for setting up internal Address translation unit(ATU)
+**/
+VOID
+PcieSetupAtu (
+ IN LsPcie *Pcie,
+ IN LsPcieInfo *Info
+);
+
+/**
+ Function for setting up PCI controller
+**/
+VOID
+PcieSetupCntrl (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN LsPcie *Pcie,
+ IN LsPcieInfo *Info
+);
+
+/**
+ Internal Helper function for read and write memory space
+**/
+EFI_STATUS
+RootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+/**
+ Internal Helper function for read and write PCI IO space
+**/
+EFI_STATUS
+RootBridgeIoIoRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+/**
+ Internal Helper function for read and write PCI configuration space
+**/
+EFI_STATUS
+RootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+);
+
+#endif
diff --git a/Platform/NXP/Include/PciLib.h b/Platform/NXP/Include/PciLib.h
new file mode 100644
index 0000000..873f0e7
--- /dev/null
+++ b/Platform/NXP/Include/PciLib.h
@@ -0,0 +1,414 @@
+/** PciLib.h
+ Pci Library containing Defines for Pci Controller configuration etc
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PCI_LIB_H__
+#define __PCI_LIB_H__
+
+/*
+ In PCI, devices have 256 bytes of configuration address space,
+ of which the first 64 bytes are standardized as follows:
+ **/
+#define LS_PCI_VENDOR_ID 0x00 // 16 bits
+#define LS_PCI_DEVICE_ID 0x02 // 16 bits
+#define LS_PCI_COMMAND 0x04 // 16 bits
+#define LS_PCI_COMMAND_IO 0x1 // Enable response in I/O space
+#define LS_PCI_COMMAND_MEMORY 0x2 // Enable response in Memory space
+#define LS_PCI_COMMAND_MASTER 0x4 // Enable bus mastering
+#define LS_PCI_COMMAND_SPECIAL 0x8 // Enable response to special cycles
+#define LS_PCI_COMMAND_INVALIDATE 0x10 // Use memory write and invalidate
+#define LS_PCI_COMMAND_VGA_PALETTE 0x20 // Enable palette snooping
+#define LS_PCI_COMMAND_PARITY 0x40 // Enable parity checking
+#define LS_PCI_COMMAND_WAIT 0x80 // Enable address/data stepping
+#define LS_PCI_COMMAND_SERR 0x100 // Enable SERR
+#define LS_PCI_COMMAND_FAST_BACK 0x200
+
+#define LS_PCI_STATUS 0x06 // 16 bits
+#define LS_PCI_STATUS_CAP_LIST 0x10 // Support Capability List
+#define LS_PCI_STATUS_66MHZ 0x20
+#define LS_PCI_STATUS_UDF 0x40
+#define LS_PCI_STATUS_FAST_BACK 0x80
+#define LS_PCI_STATUS_PARITY 0x100
+#define LS_PCI_STATUS_DEVSEL_MASK 0x600
+#define LS_PCI_STATUS_DEVSEL_FAST 0x000
+#define LS_PCI_STATUS_DEVSEL_MEDIUM 0x200
+#define LS_PCI_STATUS_DEVSEL_SLOW 0x400
+#define LS_PCI_STATUS_SIG_TARGET_ABORT 0x800
+#define LS_PCI_STATUS_REC_TARGET_ABORT 0x1000
+#define LS_PCI_STATUS_REC_MASTER_ABORT 0x2000
+#define LS_PCI_STATUS_SIG_SYSTEM_ERROR 0x4000
+#define LS_PCI_STATUS_DETECTED_PARITY 0x8000
+
+#define LS_PCI_CLASS_REVISION 0x08
+#define LS_PCI_REVISION_ID 0x08 // Revision ID
+#define LS_PCI_CLASS_PROG 0x09
+#define LS_PCI_CLASS_DEVICE 0x0a // Device class
+#define LS_PCI_CLASS_CODE 0x0b // Device class code
+#define LS_PCI_CLASS_CODE_TOO_OLD 0x00
+#define LS_PCI_CLASS_CODE_STORAGE 0x01
+#define LS_PCI_CLASS_CODE_NETWORK 0x02
+#define LS_PCI_CLASS_CODE_DISPLAY 0x03
+#define LS_PCI_CLASS_CODE_MULTIMEDIA 0x04
+#define LS_PCI_CLASS_CODE_MEMORY 0x05
+#define LS_PCI_CLASS_CODE_BRIDGE 0x06
+#define LS_PCI_CLASS_CODE_COMM 0x07
+#define LS_PCI_CLASS_CODE_PERIPHERAL 0x08
+#define LS_PCI_CLASS_CODE_INPUT 0x09
+#define LS_PCI_CLASS_CODE_DOCKING 0x0A
+#define LS_PCI_CLASS_CODE_PROCESSOR 0x0B
+#define LS_PCI_CLASS_CODE_SERIAL 0x0C
+#define LS_PCI_CLASS_CODE_WIRELESS 0x0D
+#define LS_PCI_CLASS_CODE_I2O 0x0E
+#define LS_PCI_CLASS_CODE_SATELLITE 0x0F
+#define LS_PCI_CLASS_CODE_CRYPTO 0x10
+#define LS_PCI_CLASS_CODE_DATA 0x11
+// Base Class 0x12 - 0xFE is reserved
+#define LS_PCI_CLASS_CODE_OTHER 0xFF
+
+#define LS_PCI_CLASS_SUB_CODE 0x0a // Device sub-class code
+#define LS_PCI_CLASS_SUB_CODE_TOO_OLD_NOTVGA 0x00
+#define LS_PCI_CLASS_SUB_CODE_TOO_OLD_VGA 0x01
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_SCSI 0x00
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_IDE 0x01
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_FLOPPY 0x02
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_IPIBUS 0x03
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_RAID 0x04
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_ATA 0x05
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_SATA 0x06
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_SAS 0x07
+#define LS_PCI_CLASS_SUB_CODE_STORAGE_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_ETHERNET 0x00
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_TOKENRING 0x01
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_FDDI 0x02
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_ATM 0x03
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_ISDN 0x04
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_WORLDFIP 0x05
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_PICMG 0x06
+#define LS_PCI_CLASS_SUB_CODE_NETWORK_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_DISPLAY_VGA 0x00
+#define LS_PCI_CLASS_SUB_CODE_DISPLAY_XGA 0x01
+#define LS_PCI_CLASS_SUB_CODE_DISPLAY_3D 0x02
+#define LS_PCI_CLASS_SUB_CODE_DISPLAY_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_MULTIMEDIA_VIDEO 0x00
+#define LS_PCI_CLASS_SUB_CODE_MULTIMEDIA_AUDIO 0x01
+#define LS_PCI_CLASS_SUB_CODE_MULTIMEDIA_PHONE 0x02
+#define LS_PCI_CLASS_SUB_CODE_MULTIMEDIA_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_MEMORY_RAM 0x00
+#define LS_PCI_CLASS_SUB_CODE_MEMORY_FLASH 0x01
+#define LS_PCI_CLASS_SUB_CODE_MEMORY_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_HOST 0x00
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_ISA 0x01
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_EISA 0x02
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_MCA 0x03
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_LS_PCI 0x04
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_PCMCIA 0x05
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_NUBUS 0x06
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_CARDBUS 0x07
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_RACEWAY 0x08
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_SEMI_LS_PCI 0x09
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_INFINIBAND 0x0A
+#define LS_PCI_CLASS_SUB_CODE_BRIDGE_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_COMM_SERIAL 0x00
+#define LS_PCI_CLASS_SUB_CODE_COMM_PARALLEL 0x01
+#define LS_PCI_CLASS_SUB_CODE_COMM_MULTIPORT 0x02
+#define LS_PCI_CLASS_SUB_CODE_COMM_MODEM 0x03
+#define LS_PCI_CLASS_SUB_CODE_COMM_GPIB 0x04
+#define LS_PCI_CLASS_SUB_CODE_COMM_SMARTCARD 0x05
+#define LS_PCI_CLASS_SUB_CODE_COMM_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_PIC 0x00
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_DMA 0x01
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_TIMER 0x02
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_RTC 0x03
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_HOTPLUG 0x04
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_SD 0x05
+#define LS_PCI_CLASS_SUB_CODE_PERIPHERAL_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_INPUT_KEYBOARD 0x00
+#define LS_PCI_CLASS_SUB_CODE_INPUT_DIGITIZER 0x01
+#define LS_PCI_CLASS_SUB_CODE_INPUT_MOUSE 0x02
+#define LS_PCI_CLASS_SUB_CODE_INPUT_SCANNER 0x03
+#define LS_PCI_CLASS_SUB_CODE_INPUT_GAMEPORT 0x04
+#define LS_PCI_CLASS_SUB_CODE_INPUT_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_DOCKING_GENERIC 0x00
+#define LS_PCI_CLASS_SUB_CODE_DOCKING_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_386 0x00
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_486 0x01
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_PENTIUM 0x02
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_ALPHA 0x10
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_POWERPC 0x20
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_MIPS 0x30
+#define LS_PCI_CLASS_SUB_CODE_PROCESSOR_COPROC 0x40
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_1394 0x00
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_ACCESSBUS 0x01
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_SSA 0x02
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_USB 0x03
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_FIBRECHAN 0x04
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_SMBUS 0x05
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_INFINIBAND 0x06
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_IPMI 0x07
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_SERCOS 0x08
+#define LS_PCI_CLASS_SUB_CODE_SERIAL_CANBUS 0x09
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_IRDA 0x00
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_IR 0x01
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_RF 0x10
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_BLUETOOTH 0x11
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_BROADBAND 0x12
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_80211A 0x20
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_80211B 0x21
+#define LS_PCI_CLASS_SUB_CODE_WIRELESS_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_I2O_V1_0 0x00
+#define LS_PCI_CLASS_SUB_CODE_SATELLITE_TV 0x01
+#define LS_PCI_CLASS_SUB_CODE_SATELLITE_AUDIO 0x02
+#define LS_PCI_CLASS_SUB_CODE_SATELLITE_VOICE 0x03
+#define LS_PCI_CLASS_SUB_CODE_SATELLITE_DATA 0x04
+#define LS_PCI_CLASS_SUB_CODE_CRYPTO_NETWORK 0x00
+#define LS_PCI_CLASS_SUB_CODE_CRYPTO_ENTERTAINMENT 0x10
+#define LS_PCI_CLASS_SUB_CODE_CRYPTO_OTHER 0x80
+#define LS_PCI_CLASS_SUB_CODE_DATA_DPIO 0x00
+#define LS_PCI_CLASS_SUB_CODE_DATA_PERFCNTR 0x01
+#define LS_PCI_CLASS_SUB_CODE_DATA_COMMSYNC 0x10
+#define LS_PCI_CLASS_SUB_CODE_DATA_MGMT 0x20
+#define LS_PCI_CLASS_SUB_CODE_DATA_OTHER 0x80
+
+#define LS_PCI_CACHE_LINE_SIZE 0x0c // 8 bits
+#define LS_PCI_LATENCY_TIMER 0x0d // 8 bits
+#define LS_PCI_HEADER_TYPE 0x0e // 8 bits
+#define LS_PCI_HEADER_TYPE_NORMAL 0
+#define LS_PCI_HEADER_TYPE_BRIDGE 1
+#define LS_PCI_HEADER_TYPE_CARDBUS 2
+
+#define LS_PCI_BIST 0x0f // 8 bits
+#define LS_PCI_BIST_CODE_MASK 0x0f // Return result
+#define LS_PCI_BIST_START 0x40
+#define LS_PCI_BIST_CAPABLE 0x80
+
+#define LS_PCI_BASE_ADDRESS_0 0x10 // 32 bits
+#define LS_PCI_BASE_ADDRESS_1 0x14
+#define LS_PCI_BASE_ADDRESS_2 0x18
+#define LS_PCI_BASE_ADDRESS_3 0x1c // 32 bits
+#define LS_PCI_BASE_ADDRESS_4 0x20 // 32 bits
+#define LS_PCI_BASE_ADDRESS_5 0x24 // 32 bits
+#define LS_PCI_BASE_ADDRESS_SPACE 0x01
+#define LS_PCI_BASE_ADDRESS_SPACE_IO 0x01
+#define LS_PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
+#define LS_PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
+#define LS_PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 // 32 bit address
+#define LS_PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 // Below 1M [obsolete]
+#define LS_PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 // 64 bit address
+#define LS_PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 // prefetchable?
+#define LS_PCI_BASE_ADDRESS_MEM_MASK (~0x0fULL)
+#define LS_PCI_BASE_ADDRESS_IO_MASK (~0x03ULL)
+
+// Header type 0 (normal devices)
+#define LS_PCI_CARDBUS_CIS 0x28
+#define LS_PCI_SUBSYSTEM_VENDOR_ID 0x2c
+#define LS_PCI_SUBSYSTEM_ID 0x2e
+#define LS_PCI_ROM_ADDRESS 0x30
+#define LS_PCI_ROM_ADDRESS_ENABLE 0x01
+#define LS_PCI_ROM_ADDRESS_MASK (~0x7ffULL)
+
+#define LS_PCI_CAPABILITY_LIST 0x34 // Offset of first capability list entry
+
+#define LS_PCI_INTERRUPT_LINE 0x3c // 8 bits
+#define LS_PCI_INTERRUPT_PIN 0x3d // 8 bits
+#define LS_PCI_MIN_GNT 0x3e // 8 bits
+#define LS_PCI_MAX_LAT 0x3f // 8 bits
+
+// Header type 1 (PCI-to-PCI bridges)
+#define LS_PCI_PRIMARY_BUS 0x18 // Primary bus number
+#define LS_PCI_SECONDARY_BUS 0x19 // Secondary bus number
+#define LS_PCI_SUBORDINATE_BUS 0x1a
+#define LS_PCI_SEC_LATENCY_TIMER 0x1b
+#define LS_PCI_IO_BASE 0x1c // I/O range behind the bridge
+#define LS_PCI_IO_LIMIT 0x1d
+#define LS_PCI_IO_RANGE_TYPE_MASK 0x0f // I/O bridging type
+#define LS_PCI_IO_RANGE_TYPE_16 0x00
+#define LS_PCI_IO_RANGE_TYPE_32 0x01
+#define LS_PCI_IO_RANGE_MASK ~0x0f
+#define LS_PCI_SEC_STATUS 0x1e
+#define LS_PCI_MEMORY_BASE 0x20 // Memory range behind
+#define LS_PCI_MEMORY_LIMIT 0x22
+#define LS_PCI_MEMORY_RANGE_TYPE_MASK 0x0f
+#define LS_PCI_MEMORY_RANGE_MASK ~0x0f
+#define LS_PCI_PREF_MEMORY_BASE 0x24 // Prefetchable memory range behind
+#define LS_PCI_PREF_MEMORY_LIMIT 0x26
+#define LS_PCI_PREF_RANGE_TYPE_MASK 0x0f
+#define LS_PCI_PREF_RANGE_TYPE_32 0x00
+#define LS_PCI_PREF_RANGE_TYPE_64 0x01
+#define LS_PCI_PREF_RANGE_MASK ~0x0f
+#define LS_PCI_PREF_BASE_UPPER32 0x28 // Upper half of prefetchable memory range
+#define LS_PCI_PREF_LIMIT_UPPER32 0x2c
+#define LS_PCI_IO_BASE_UPPER16 0x30 // Upper half of I/O addresses
+#define LS_PCI_IO_LIMIT_UPPER16 0x32
+#define LS_PCI_ROM_ADDRESS1 0x38 // Same as LS_PCI_ROM_ADDRESS, but for htype 1
+#define LS_PCI_BRIDGE_CONTROL 0x3e
+#define LS_PCI_BRIDGE_CTL_PARITY 0x01
+#define LS_PCI_BRIDGE_CTL_SERR 0x02
+#define LS_PCI_BRIDGE_CTL_NO_ISA 0x04
+#define LS_PCI_BRIDGE_CTL_VGA 0x08
+#define LS_PCI_BRIDGE_CTL_MASTER_ABORT 0x20 // Report master aborts
+#define LS_PCI_BRIDGE_CTL_BUS_RESET 0x40 // Secondary bus reset
+#define LS_PCI_BRIDGE_CTL_FAST_BACK 0x80
+
+#define LS_PCI_ERREN 0x48 // Error Enable
+#define LS_PCI_ERRSTS 0x49 // Error Status
+#define LS_PCI_BRDGOPT1 0x4A
+#define LS_PCI_PLBSESR0 0x4C
+#define LS_PCI_PLBSESR1 0x50
+#define LS_PCI_PLBSEAR 0x54
+#define LS_PCI_CAPID 0x58
+#define LS_PCI_NEXTITEMPTR 0x59
+#define LS_PCI_PMC 0x5A
+#define LS_PCI_PMCSR 0x5C
+#define LS_PCI_PMCSRBSE 0x5E
+#define LS_PCI_BRDGOPT2 0x60 // PCI Bridge Options 2
+#define LS_PCI_PMSCRR 0x64
+
+// Header type 2 (CardBus bridges)
+#define LS_PCI_CB_CAPABILITY_LIST 0x14
+// 0x15 reserved
+#define LS_PCI_CB_SEC_STATUS 0x16 // Secondary status
+#define LS_PCI_CB_PRIMARY_BUS 0x18 // PCI bus number
+#define LS_PCI_CB_CARD_BUS 0x19
+#define LS_PCI_CB_SUBORDINATE_BUS 0x1a // Subordinate bus number
+#define LS_PCI_CB_LATENCY_TIMER 0x1b
+#define LS_PCI_CB_MEMORY_BASE_0 0x1c
+#define LS_PCI_CB_MEMORY_LIMIT_0 0x20
+#define LS_PCI_CB_MEMORY_BASE_1 0x24
+#define LS_PCI_CB_MEMORY_LIMIT_1 0x28
+#define LS_PCI_CB_IO_BASE_0 0x2c
+#define LS_PCI_CB_IO_BASE_0_HI 0x2e
+#define LS_PCI_CB_IO_LIMIT_0 0x30
+#define LS_PCI_CB_IO_LIMIT_0_HI 0x32
+#define LS_PCI_CB_IO_BASE_1 0x34
+#define LS_PCI_CB_IO_BASE_1_HI 0x36
+#define LS_PCI_CB_IO_LIMIT_1 0x38
+#define LS_PCI_CB_IO_LIMIT_1_HI 0x3a
+#define LS_PCI_CB_IO_RANGE_MASK ~0x03
+#define LS_PCI_CB_BRIDGE_CONTROL 0x3e
+#define LS_PCI_CB_BRIDGE_CTL_PARITY 0x01 // Similar to standard bridge control register
+#define LS_PCI_CB_BRIDGE_CTL_SERR 0x02
+#define LS_PCI_CB_BRIDGE_CTL_ISA 0x04
+#define LS_PCI_CB_BRIDGE_CTL_VGA 0x08
+#define LS_PCI_CB_BRIDGE_CTL_MASTER_ABORT 0x20
+#define LS_PCI_CB_BRIDGE_CTL_CB_RESET 0x40 // CardBus reset
+#define LS_PCI_CB_BRIDGE_CTL_16BIT_INT 0x80
+#define LS_PCI_CB_BRIDGE_CTL_PREFETCH_MEM0 0x100 // Prefetch enable for both memory regions
+#define LS_PCI_CB_BRIDGE_CTL_PREFETCH_MEM1 0x200
+#define LS_PCI_CB_BRIDGE_CTL_POST_WRITES 0x400
+#define LS_PCI_CB_SUBSYSTEM_VENDOR_ID 0x40
+#define LS_PCI_CB_SUBSYSTEM_ID 0x42
+#define LS_PCI_CB_LEGACY_MODE_BASE 0x44 // 16-bit PC Card legacy mode base address (ExCa)
+
+// Defines of Capability lists
+#define LS_PCI_CAP_LIST_ID 0 // Capability ID
+#define LS_PCI_CAP_ID_PM 0x01 // Power Management
+#define LS_PCI_CAP_ID_AGP 0x02
+#define LS_PCI_CAP_ID_VPD 0x03
+#define LS_PCI_CAP_ID_SLOTID 0x04
+#define LS_PCI_CAP_ID_MSI 0x05
+#define LS_PCI_CAP_ID_CHSWP 0x06
+#define LS_PCI_CAP_ID_EXP 0x10
+#define LS_PCI_CAP_LIST_NEXT 1 // Next capability in the list
+#define LS_PCI_CAP_FLAGS 2 // Capability defined flags (16 bits)
+#define LS_PCI_CAP_SIZEOF 4
+
+// Power Management Registers
+#define LS_PCI_PM_CAP_VER_MASK 0x0007
+#define LS_PCI_PM_CAP_PME_CLOCK 0x0008
+#define LS_PCI_PM_CAP_AUX_POWER 0x0010
+#define LS_PCI_PM_CAP_DSI 0x0020
+#define LS_PCI_PM_CAP_D1 0x0200
+#define LS_PCI_PM_CAP_D2 0x0400
+#define LS_PCI_PM_CAP_PME 0x0800
+#define LS_PCI_PM_CTRL 4
+#define LS_PCI_PM_CTRL_STATE_MASK 0x0003
+#define LS_PCI_PM_CTRL_PME_ENABLE 0x0100
+#define LS_PCI_PM_CTRL_DATA_SEL_MASK 0x1e00
+#define LS_PCI_PM_CTRL_DATA_SCALE_MASK 0x6000
+#define LS_PCI_PM_CTRL_PME_STATUS 0x8000
+#define LS_PCI_PM_PPB_EXTENSIONS 6
+#define LS_PCI_PM_PPB_B2_B3 0x40
+#define LS_PCI_PM_BPCC_ENABLE 0x80
+#define LS_PCI_PM_DATA_REGISTER 7
+#define LS_PCI_PM_SIZEOF 8
+
+// AGP registers defines
+#define LS_PCI_AGP_VERSION 2
+#define LS_PCI_AGP_RFU 3
+#define LS_PCI_AGP_STATUS 4
+#define LS_PCI_AGP_STATUS_RQ_MASK 0xff000000
+#define LS_PCI_AGP_STATUS_SBA 0x0200
+#define LS_PCI_AGP_STATUS_64BIT 0x0020
+#define LS_PCI_AGP_STATUS_FW 0x0010
+#define LS_PCI_AGP_STATUS_RATE4 0x0004
+#define LS_PCI_AGP_STATUS_RATE2 0x0002
+#define LS_PCI_AGP_STATUS_RATE1 0x0001
+#define LS_PCI_AGP_COMMAND 8
+#define LS_PCI_AGP_COMMAND_RQ_MASK 0xff000000
+#define LS_PCI_AGP_COMMAND_SBA 0x0200
+#define LS_PCI_AGP_COMMAND_AGP 0x0100
+#define LS_PCI_AGP_COMMAND_64BIT 0x0020
+#define LS_PCI_AGP_COMMAND_FW 0x0010
+#define LS_PCI_AGP_COMMAND_RATE4 0x0004
+#define LS_PCI_AGP_COMMAND_RATE2 0x0002
+#define LS_PCI_AGP_COMMAND_RATE1 0x0001
+#define LS_PCI_AGP_SIZEOF 12
+
+// Defines for PCI-X registers
+#define LS_PCI_X_CMD_DPERR_E 0x0001
+#define LS_PCI_X_CMD_ERO 0x0002
+#define LS_PCI_X_CMD_MAX_READ 0x0000
+#define LS_PCI_X_CMD_MAX_SPLIT 0x0030
+#define LS_PCI_X_CMD_VERSION(x) (((x) >> 12) & 3)
+
+// Register of Slot Identification
+#define LS_PCI_SID_ESR 2 // Expansion Slot Register
+#define LS_PCI_SID_ESR_NSLOTS 0x1f // Number of expansion slots available
+#define LS_PCI_SID_ESR_FIC 0x20 // First In Chassis Flag
+#define LS_PCI_SID_CHASSIS_NR 3 // Chassis Number
+
+#define LS_PCI_MSI_FLAGS 2
+#define LS_PCI_MSI_FLAGS_64BIT 0x80
+#define LS_PCI_MSI_FLAGS_QSIZE 0x70
+#define LS_PCI_MSI_FLAGS_QMASK 0x0e
+#define LS_PCI_MSI_FLAGS_ENABLE 0x01
+#define LS_PCI_MSI_RFU 3
+#define LS_PCI_MSI_ADDRESS_LO 4
+#define PCI_MSI_ADDRESS_HI 8
+#define LS_PCI_MSI_DATA_32 8
+#define LS_PCI_MSI_DATA_64 12
+
+#define LS_PCI_MAX_PCI_DEVICES 32
+#define LS_PCI_MAX_PCI_FUNCTIONS 8
+
+#define LS_PCI_FIND_CAP_TTL 0x48
+#define CAP_START_POS 0x40
+
+#define LS_PCI_REGION_MEM 0x00000000 // PCI memory space
+#define LS_PCI_REGION_IO 0x00000001 // PCI IO space
+#define LS_PCI_REGION_TYPE 0x00000001
+#define LS_PCI_REGION_PREFETCH 0x00000008 // prefetchable PCI memory
+#define LS_PCI_REGION_SYS_MEMORY 0x00000100 // System memory
+#define LS_PCI_REGION_RO 0x00000200 // Read-only memory
+
+#define PCI_BUS(Dev) (((Dev) >> 16) & 0xff)
+#define PCI_DEV(Dev) (((Dev) >> 11) & 0x1f)
+#define PCI_FUNC(Dev) (((Dev) >> 8) & 0x7)
+#define PCI_BDF(B,D,F) ((B) << 16 | (D) << 11 | (F) << 8)
+
+#define PCI_ANY_ID (~0)
+
+#define INDIRECT_TYPE_NO_PCIE_LINK 1
+
+#endif /* _PCI_LIB_H */
diff --git a/Platform/NXP/Library/PciHostBridgeLib/PciCntrl.c b/Platform/NXP/Library/PciHostBridgeLib/PciCntrl.c
new file mode 100644
index 0000000..942e04e
--- /dev/null
+++ b/Platform/NXP/Library/PciHostBridgeLib/PciCntrl.c
@@ -0,0 +1,628 @@
+/** PciCntrl.c
+ Provides the basic interfaces to be used by PCI Root Bridge IO protocol
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include <Library/BeIoLib.h>
+#include "PciHostBridge.h"
+
+PCI_ROOT_BRIDGE_INSTANCE *RootBridgeHead;
+
+/**
+ Function for setting up PCI region
+**/
+VOID
+PciSetRegion (
+ IN PciRegion *Reg,
+ IN PciAddrT BusStart,
+ IN PhysAddrT PhysStart,
+ IN PciSizeT Size,
+ IN UINTN Flags
+)
+{
+ Reg->BusStart = BusStart;
+ Reg->PhysStart = PhysStart;
+ Reg->Size = Size;
+ Reg->Flags = Flags;
+}
+
+/**
+ Function to set PCI Space
+ - Configuration space
+ - Memory Space
+ - I/O Space
+**/
+VOID
+SetLSPcieInfo (
+ IN LsPcieInfo *PcieInfo,
+ IN UINTN Num
+)
+{
+ UINTN pciePhyAddr, pcieSysaddr;
+
+ pciePhyAddr=0;
+ pcieSysaddr=0;
+
+ switch(Num){
+ case 1:
+ pciePhyAddr = PcdGet64 (PcdPciExp1BaseAddr);
+ pcieSysaddr = PcdGet64 (PcdPciExp1SysAddr);
+ break;
+ case 2:
+ pciePhyAddr = PcdGet64 (PcdPciExp2BaseAddr);
+ pcieSysaddr = PcdGet64 (PcdPciExp2SysAddr);
+ break;
+ case 3:
+ pciePhyAddr = PcdGet64 (PcdPciExp3BaseAddr);
+ pcieSysaddr = PcdGet64 (PcdPciExp3SysAddr);
+ break;
+ case 4:
+ pciePhyAddr = PcdGet64 (PcdPciExp4BaseAddr);
+ pcieSysaddr = PcdGet64 (PcdPciExp4SysAddr);
+ break;
+ }
+
+ PcieInfo->Regs = pcieSysaddr;
+ PcieInfo->Cfg0Phys = LS_PCIE_CFG0_PHYS_OFF + pciePhyAddr;
+ PcieInfo->Cfg0Size = LS_PCIE_CFG0_SIZE;
+ PcieInfo->Cfg1Phys = LS_PCIE_CFG1_PHYS_OFF + pciePhyAddr;
+ PcieInfo->Cfg1Size = LS_PCIE_CFG1_SIZE;
+ PcieInfo->MemBus = LS_PCIE_MEM_BUS;
+ PcieInfo->MemPhys = LS_PCIE_MEM_PHYS_OFF + pciePhyAddr;
+ PcieInfo->MemSize = LS_PCIE_MEM_SIZE;
+ PcieInfo->IoBus = LS_PCIE_IO_BUS;
+ PcieInfo->IoPhys = LS_PCIE_IO_PHYS_OFF + pciePhyAddr;
+ PcieInfo->IoSize = LS_PCIE_IO_SIZE;
+ PcieInfo->PciNum = Num;
+
+ if (FeaturePcdGet (PcdPciDebug) == TRUE) {
+ DEBUG ((DEBUG_INFO, "In SET_PCIE_INFO: %d\n", Num));
+ DEBUG ((DEBUG_INFO, "PciNum:%d Info CFG Values: %016llx %016llx:%016llx %016llx %016llx\n",
+ (UINT64)PcieInfo->PciNum,
+ (UINT64)PcieInfo->Regs,
+ (UINT64)PcieInfo->Cfg0Phys,
+ (UINT64)PcieInfo->Cfg0Size,
+ (UINT64)PcieInfo->Cfg1Phys,
+ (UINT64)PcieInfo->Cfg1Size));
+ DEBUG ((DEBUG_INFO, "Info Mem Values: %016llx:%016llx %016llx\n",
+ (UINT64)PcieInfo->MemBus,
+ (UINT64)PcieInfo->MemPhys,
+ (UINT64)PcieInfo->MemSize));
+ DEBUG ((DEBUG_INFO, "Info IO Values: %016llx:%016llx %016llx\n",
+ (UINT64)PcieInfo->IoBus,
+ (UINT64)PcieInfo->IoPhys,
+ (UINT64)PcieInfo->IoSize));
+ }
+}
+
+/**
+ Function to check PCIe link state
+**/
+INTN
+PcieLinkState (
+ IN LsPcie *Pcie
+)
+{
+ UINT32 State;
+ if (FeaturePcdGet (PcdPciLutBigEndian)) {
+ State = BeMmioRead32 ((UINTN)(Pcie->Dbi) + LS_PCIE_LUT_BASE + LS_PCIE_LUT_DBG) &
+ LS_LTSSM_STATE_MASK;
+ }
+ else {
+ State = MmioRead32 ((UINTN)(Pcie->Dbi) + LS_PCIE_LUT_BASE + LS_PCIE_LUT_DBG) &
+ LS_LTSSM_STATE_MASK;
+ }
+
+ if (State < LS_LTSSM_PCIE_L0) {
+ DEBUG ((DEBUG_INFO," Pcie Link error. LTSSM=0x%2x\n",
+ State));
+ return EFI_SUCCESS;
+ }
+
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Helper function to check PCIe link is up
+ Download the speed to gen1
+**/
+INTN
+PcieLinkUp (
+ IN LsPcie *Pcie
+)
+{
+ INTN State;
+ UINT32 Cap;
+
+ State = PcieLinkState (Pcie);
+ if (State) {
+ return State;
+ }
+
+ // Try to download speed to gen1
+ Cap = MmioRead32 ((UINTN)(Pcie->Dbi) + LS_PCIE_LINK_CAP);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_LINK_CAP, (UINT32)(Cap & (~LS_PCIE_LINK_SPEED_MASK)) | 1);
+ State = PcieLinkState (Pcie);
+ if (State) {
+ return State;
+ }
+
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_LINK_CAP, Cap);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to set up PCI configuration(cfg0) space
+**/
+VOID
+PcieCfg0SetBusdev (
+ IN LsPcie *Pcie,
+ IN UINT32 BusDev
+)
+{
+ MmioWrite32 ((UINTN)(Pcie->Dbi + LS_PCIE_ATU_VIEWPORT),
+ LS_PCIE_ATU_REGION_OUTBOUND | LS_PCIE_ATU_REGION_INDEX0);
+ MmioWrite32 ((UINTN)(Pcie->Dbi + LS_PCIE_ATU_LOWER_TARGET), BusDev);
+}
+
+/**
+ Function to set up PCI configuration(cfg1) space
+**/
+VOID
+PcieCfg1SetBusdev (
+ IN LsPcie *Pcie,
+ IN UINT32 BusDev
+)
+{
+ MmioWrite32 ((UINTN)(Pcie->Dbi + LS_PCIE_ATU_VIEWPORT),
+ LS_PCIE_ATU_REGION_OUTBOUND | LS_PCIE_ATU_REGION_INDEX1);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_TARGET, BusDev);
+}
+
+/**
+ Function to set up internal address translation window for inbound
+ transaction
+**/
+VOID
+PcieIatuInboundSet (
+ IN LsPcie *Pcie,
+ IN UINT32 Idx,
+ IN UINT32 Bar,
+ IN UINT64 Phys
+)
+{
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_VIEWPORT, (UINT32)(LS_PCIE_ATU_REGION_INBOUND | Idx));
+
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_BASE, Phys);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_UPPER_BASE, (UINT32)(Phys >> 32));
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_TARGET, (UINT32)Phys);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_UPPER_TARGET, (UINT32)(Phys >> 32));
+
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_CR1, LS_PCIE_ATU_TYPE_MEM);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_CR2, LS_PCIE_ATU_ENABLE);
+}
+
+/**
+ Function to set up internal address translation window for outbound
+ transaction
+**/
+VOID
+PcieIatuOutboundSet (
+ IN LsPcie *Pcie,
+ IN UINT32 Idx,
+ IN UINT32 Type,
+ IN UINT64 Phys,
+ IN UINT64 BusAddr,
+ IN UINT64 Size
+)
+{
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_VIEWPORT, (UINT32)(LS_PCIE_ATU_REGION_OUTBOUND | Idx));
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_BASE, Phys);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_UPPER_BASE, (UINT32)(Phys >> 32));
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LIMIT, (UINT32)(Phys + Size -1));
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_TARGET, (UINT32)BusAddr);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_UPPER_TARGET, (UINT32)(BusAddr >> 32));
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_CR1, (UINT32)Type);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_CR2, LS_PCIE_ATU_ENABLE);
+}
+
+EFI_STATUS
+PciSkipDev (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev
+)
+{
+ // Do not skip controller
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to check whether PCIe address is valid
+**/
+EFI_STATUS
+PcieAddrValid (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev
+)
+{
+ if ((((Dev >> 19)) & 0x1f) > 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // No support for multi-function
+ if ((((Dev >> 16)) & 0x07) > 0) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ // Controller does not support multi-function in RC mode
+ if (((((Dev) >> 24) & 0xff) == PrivateData->FirstBusno) && ((((Dev) >> 16) & 0x7) > 0)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to read from PCI config space
+
+ @param Pointer to PCI_ROOT_BRIDGE_INSTANCE
+
+ @return The value(32-bit) read
+
+**/
+
+EFI_STATUS
+PcieReadConfig (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Where,
+ IN OUT UINT32 *Val
+)
+{
+ LsPcie *Pcie;
+ UINT32 BusDev, *Addr;
+
+ *Val = 0x00000000;
+ Pcie = PrivateData->Pcie;
+
+ if (PcieAddrValid (PrivateData, Dev)) {
+ *Val = 0xffffffff;
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((((Dev) >> 24) & 0xff) == PrivateData->FirstBusno) {
+ Addr = Pcie->Dbi + Where;
+ } else {
+ BusDev = Dev;
+
+ if ((((Dev) >> 24) & 0xff) == PrivateData->FirstBusno + 1) {
+ PcieCfg0SetBusdev (Pcie, BusDev);
+ Addr = (VOID *)Pcie->VaCfg0 + Where;
+ } else {
+ PcieCfg1SetBusdev (Pcie, BusDev);
+ Addr = (VOID *)Pcie->VaCfg1 + Where;
+ }
+ }
+
+ *Val = MmioRead32 ((UINTN)Addr);
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to read byte from PCI config space
+
+ @param Pointer to PCI_ROOT_BRIDGE_INSTANCE
+
+ @return The value(8-bit) read
+
+**/
+
+EFI_STATUS
+PcieReadConfigByte (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ IN OUT UINT8 *Val
+)
+{
+ UINT32 Val32;
+
+ if (EFI_ERROR (PcieReadConfig (PrivateData, Dev, Offset & 0xfc, &Val32))) {
+ *Val = -1;
+ return EFI_DEVICE_ERROR;
+ }
+
+ *Val = (Val32 >> ((Offset & (INT32)0x03) * 8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to read word(16-bit) from PCI config space
+
+ @param Pointer to PCI_ROOT_BRIDGE_INSTANCE
+
+ @return The value(16-bit) read
+
+**/
+
+EFI_STATUS
+PcieReadConfigWord (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ IN OUT UINT16 *Val
+)
+{
+ UINT32 Val32;
+
+ if (EFI_ERROR (PcieReadConfig (PrivateData, Dev, Offset & 0xfc, &Val32))) {
+ *Val = -1;
+ return EFI_DEVICE_ERROR;
+ }
+
+ *Val = (UINT16)(Val32 >> ((Offset & (INT32)0x02) * 8));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to write byte to PCI config space
+
+ @param Pointer to PCI_ROOT_BRIDGE_INSTANCE
+
+ @return EFI_SUCCESS (8-bit value written)
+
+**/
+
+EFI_STATUS
+PcieWriteConfigByte (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ OUT UINT8 Val
+)
+{
+ UINT32 Val32, Mask, Ldata, Shift;
+
+ if (EFI_ERROR (PcieReadConfig (PrivateData, Dev, Offset & 0xfc, &Val32))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Shift = ((Offset & (INT32)0x03) * 8);
+ Ldata = (((UINT32)Val) & 0x000000ff) << Shift;
+ Mask = 0x000000ff << Shift;
+ Val32 = (Val32 & ~Mask) | Ldata;
+
+ if (EFI_ERROR (PcieWriteConfig (PrivateData, Dev, Offset & 0xfc, Val32))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to write word to PCI config space
+
+ @param Pointer to PCI_ROOT_BRIDGE_INSTANCE
+
+ @return EFI_SUCCESS (16-bit value written)
+
+**/
+
+EFI_STATUS
+PcieWriteConfigWord (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Offset,
+ OUT UINT16 Val
+)
+{
+ UINT32 Val32, Mask, Ldata, Shift;
+
+ if (EFI_ERROR (PcieReadConfig (PrivateData, Dev, Offset & 0xfc, &Val32))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Shift = ((Offset & (INT32)0x02) * 8);
+ Ldata = (((UINT32)Val) & 0x0000ffff) << Shift;
+ Mask = 0x0000ffff << Shift;
+ Val32 = (Val32 & ~Mask) | Ldata;
+
+ if (EFI_ERROR (PcieWriteConfig (PrivateData, Dev, Offset & 0xfc, Val32))) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to write to PCI config space
+
+ @param Pointer to PCI_ROOT_BRIDGE_INSTANCE
+
+ @return EFI_SUCCESS (32-bit value written)
+
+**/
+
+EFI_STATUS
+PcieWriteConfig (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN UINT32 Dev,
+ IN INT32 Where,
+ IN UINT32 Val
+)
+{
+ LsPcie *Pcie;
+ UINT32 BusDev, *Addr;
+
+ Pcie = PrivateData->Pcie;
+
+ if (PcieAddrValid (PrivateData, Dev)) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ if ((((Dev) >> 24) & 0xff) == PrivateData->FirstBusno) {
+ Addr = Pcie->Dbi + (Where & ~0x3);
+ } else {
+ BusDev = Dev;
+
+ if ((((Dev) >> 24) & 0xff) == PrivateData->FirstBusno + 1) {
+ PcieCfg0SetBusdev (Pcie, BusDev);
+ Addr = (VOID *)Pcie->VaCfg0 + (Where & ~0x3);
+ } else {
+ PcieCfg1SetBusdev (Pcie, BusDev);
+ Addr = (VOID *)Pcie->VaCfg1 + (Where & ~0x3);
+ }
+ }
+
+ MmioWrite32 ((UINTN)Addr, (UINT32)Val);
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to set up address translation unit for PCI
+ inbound transactions
+**/
+VOID
+PcieSetupAtuInbound (
+ IN LsPcie *Pcie,
+ IN LsPcieInfo *Info
+)
+{
+ UINT32 ValIn;
+ UINT32 ValOut;
+ UINT32 *Addr;
+
+ ValIn = 0x00000000;
+ ValOut = 0x28282828;
+ Addr = (UINT32 *)0x80080000;
+
+ MmioWrite32 ((UINTN)Addr, (UINT32)ValOut);
+ DEBUG ((DEBUG_INFO,"\nValue: %08lx written on Addr: %08lx\n", ValOut, Addr));
+ ValIn = MmioRead32 ((UINTN)Addr);
+ DEBUG ((DEBUG_INFO, "Value Read: %08lx from Address: %llx\n", ValIn, Addr));
+ // ATU 2 : OUTBOUND : MEM
+ PcieIatuInboundSet (Pcie, LS_PCIE_ATU_REGION_INDEX2, 1, 0x80080000);
+
+ Addr = (VOID *)Pcie->VaCfg0 + 0x40000000;
+ ValIn = MmioRead32 ((UINTN)Addr);
+ DEBUG ((DEBUG_INFO, "Inbound: Value Read: %08lx from Address: %llx\n", ValIn, Addr));
+ Addr = (VOID *)Pcie->VaCfg0 + 0x00000000;
+ ValIn = MmioRead32 ((UINTN)Addr);
+ DEBUG ((DEBUG_INFO, "Inbound: Value Read: %08lx from Address: %llx\n", ValIn, Addr));
+ Addr = (UINT32 *)0x80080000;
+ ValIn = MmioRead32((UINTN)Addr);
+ DEBUG ((DEBUG_INFO, "Inbound: Value Read: %08lx from Address: %llx\n", ValIn, Addr));
+
+}
+
+/**
+ Function to set up address translation unit for PCI
+ outbound transactions
+**/
+VOID
+PcieSetupAtu (
+ IN LsPcie *Pcie,
+ IN LsPcieInfo *Info
+)
+{
+ // ATU 0 : OUTBOUND : CFG0
+ PcieIatuOutboundSet (Pcie, LS_PCIE_ATU_REGION_INDEX0,
+ LS_PCIE_ATU_TYPE_CFG0,
+ Info->Cfg0Phys,
+ 0,
+ Info->Cfg0Size);
+
+ // ATU 1 : OUTBOUND : CFG1
+ PcieIatuOutboundSet (Pcie, LS_PCIE_ATU_REGION_INDEX1,
+ LS_PCIE_ATU_TYPE_CFG1,
+ Info->Cfg1Phys,
+ 0,
+ Info->Cfg1Size);
+
+ // ATU 2 : OUTBOUND : MEM
+ PcieIatuOutboundSet (Pcie, LS_PCIE_ATU_REGION_INDEX2,
+ LS_PCIE_ATU_TYPE_MEM,
+ Info->MemPhys,
+ Info->MemBus,
+ //0x10000000,
+ Info->MemSize);
+
+ // ATU 3 : OUTBOUND : IO
+ PcieIatuOutboundSet (Pcie, LS_PCIE_ATU_REGION_INDEX3,
+ LS_PCIE_ATU_TYPE_IO,
+ Info->IoPhys,
+ Info->IoBus,
+ Info->IoSize);
+
+ if (FeaturePcdGet (PcdPciDebug) == TRUE) {
+ INTN Cnt;
+ UINTN AddrTemp;
+ for (Cnt = 0; Cnt <= LS_PCIE_ATU_REGION_INDEX3; Cnt++) {
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_VIEWPORT,
+ (UINT32)(LS_PCIE_ATU_REGION_OUTBOUND | Cnt));
+ DEBUG ((DEBUG_INFO,"iATU%d:\n", Cnt));
+ AddrTemp = (UINTN)((UINTN)Pcie->Dbi + LS_PCIE_ATU_VIEWPORT);
+ DEBUG((DEBUG_INFO,"iATU%d VIEWPORT REG Addr:%08lx Val:%08lx\n",
+ Cnt, AddrTemp, MmioRead32(AddrTemp)));
+ DEBUG ((DEBUG_INFO,"iATU%d VIEWPORT REG:%08lx\n", Cnt,
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_VIEWPORT)));
+ DEBUG ((DEBUG_INFO,"\tLOWER PHYS 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_BASE)));
+ DEBUG ((DEBUG_INFO,"\tUPPER PHYS 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_UPPER_BASE)));
+ DEBUG ((DEBUG_INFO,"\tLOWER BUS 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LOWER_TARGET)));
+ DEBUG ((DEBUG_INFO,"\tUPPER BUS 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_UPPER_TARGET)));
+ DEBUG ((DEBUG_INFO,"\tLIMIT 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_LIMIT)));
+ DEBUG ((DEBUG_INFO,"\tCR1 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_CR1)));
+ DEBUG ((DEBUG_INFO,"\tCR2 0x%08x\n",
+ MmioRead32 ((UINTN)Pcie->Dbi + LS_PCIE_ATU_CR2)));
+ }
+ }
+}
+
+/**
+ Function to set up PCI controller
+ -Setup ATU
+ -Setup Root complex class
+**/
+VOID
+PcieSetupCntrl (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN LsPcie *Pcie,
+ IN LsPcieInfo *Info
+)
+{
+ UINTN Dev;
+
+ Dev = ((PrivateData->FirstBusno) << 16 | (0) << 11 | (0) << 8);
+
+ if (FeaturePcdGet (PcdPciDebug) == TRUE) {
+ DEBUG ((DEBUG_INFO, "Going to SetUp IATU\n\n"));
+ }
+
+ PcieSetupAtu (Pcie, Info);
+
+ PcieWriteConfig (PrivateData, Dev, LS_PCI_BASE_ADDRESS_0, 0);
+
+ // program correct class for RC
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_DBI_RO_WR_EN, (UINT32)1);
+ PcieWriteConfigWord (PrivateData, Dev, LS_PCI_CLASS_DEVICE,
+ PCI_CLASS_BRIDGE_PCI);
+ MmioWrite32 ((UINTN)Pcie->Dbi + LS_PCIE_DBI_RO_WR_EN, (UINT32)0);
+}
diff --git a/Platform/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf b/Platform/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
new file mode 100644
index 0000000..f281357
--- /dev/null
+++ b/Platform/NXP/Library/PciHostBridgeLib/PciHostBridgeLib.inf
@@ -0,0 +1,49 @@
+/* PciHostBridgeLib.inf
+#
+# Component description file for PCI root Bridge Library
+#
+# Copyright 2017 NXP
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+*/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = PciHostBridgeLib
+ FILE_GUID = c0f5dfa0-7599-11e0-9865-0002a5d5c61b
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciHostBridgeLib
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ Platform/NXP/NxpQoriqLs.dec
+ Silicon/NXP/Chassis/Chassis2/Chassis2.dec
+
+[Sources.common]
+ PciCntrl.c
+ PciRbLib.c
+
+[FixedPcd]
+ gNxpQoriqLsTokenSpaceGuid.PcdPciDebug
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp4BaseAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp1SysAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp2SysAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp3SysAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp4SysAddr
+ gArmTokenSpaceGuid.PcdSystemMemoryBase
+ gNxpQoriqLsTokenSpaceGuid.PcdPcieLutBase
+ gNxpQoriqLsTokenSpaceGuid.PcdPcieLutDbg
+ gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian
diff --git a/Platform/NXP/Library/PciHostBridgeLib/PciRbLib.c b/Platform/NXP/Library/PciHostBridgeLib/PciRbLib.c
new file mode 100644
index 0000000..4ebfc73
--- /dev/null
+++ b/Platform/NXP/Library/PciHostBridgeLib/PciRbLib.c
@@ -0,0 +1,331 @@
+/** PciRbLib.c
+ Functions supporting PCI Root Bridge Io Protocol
+
+ Some part of code is inspired from EDK II, file:
+ PcAtChipsetPkg/PciHostBridgeDxe/PciRootBridgeIo.c
+
+ Copyright (c) 2008 - 2012, Intel Corporation. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "PciHostBridge.h"
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mInStride[] = {
+ 1, // EfiPciWidthUint8
+ 2, // EfiPciWidthUint16
+ 4, // EfiPciWidthUint32
+ 8, // EfiPciWidthUint64
+ 0, // EfiPciWidthFifoUint8
+ 0, // EfiPciWidthFifoUint16
+ 0, // EfiPciWidthFifoUint32
+ 0, // EfiPciWidthFifoUint64
+ 1, // EfiPciWidthFillUint8
+ 2, // EfiPciWidthFillUint16
+ 4, // EfiPciWidthFillUint32
+ 8 // EfiPciWidthFillUint64
+};
+
+//
+// Lookup table for increment values based on transfer widths
+//
+UINT8 mOutStride[] = {
+ 1, // EfiPciWidthUint8
+ 2, // EfiPciWidthUint16
+ 4, // EfiPciWidthUint32
+ 8, // EfiPciWidthUint64
+ 1, // EfiPciWidthFifoUint8
+ 2, // EfiPciWidthFifoUint16
+ 4, // EfiPciWidthFifoUint32
+ 8, // EfiPciWidthFifoUint64
+ 0, // EfiPciWidthFillUint8
+ 0, // EfiPciWidthFillUint16
+ 0, // EfiPciWidthFillUint32
+ 0 // EfiPciWidthFillUint64
+};
+
+/**
+ Function to validate parameters(Operation type,Supported width) for
+ root bridge io operation
+
+ @param This Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+ @param OperationType Operation type(Mem,I/O,Config)
+
+ @param Width Pointer to EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH
+
+ @return EFI_SUCCESS Paramters check is ok for operation
+
+ @return EFI_INVALID_PARAMETER Inavlide parameters
+
+**/
+STATIC EFI_STATUS
+RootBridgeIoCheckParameter (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN OPERATION_TYPE OperationType,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ if ((Width >= EfiPciWidthMaximum) || (Width < EfiPciWidthUint8) || (NULL == Buffer)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write memory space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoMemRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ UINT8 InStride;
+ UINT8 OutStride;
+ UINT8 *Uint8Buffer;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ Status = RootBridgeIoCheckParameter (This, MemOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((Address < LS_PCIE_MEM_PHYS_OFF) ||
+ (Address >= ((UINT32)LS_PCIE_MEM_PHYS_OFF +
+ LS_PCIE_MEM_SIZE))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(This);
+ if (PrivateData == NULL ) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Address += PrivateData->PciBaseAddress64;
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+
+ for (Uint8Buffer = Buffer; Count > 0; Address += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (Width) {
+ case EfiPciWidthUint8:
+ MmioWrite8 ((UINTN)Address, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ MmioWrite16 ((UINTN)Address, *((UINT16 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint32:
+ MmioWrite32 ((UINTN)Address, *((UINT32 *)Uint8Buffer));
+ break;
+ case EfiPciWidthUint64:
+ MmioWrite64 ((UINTN)Address, *((UINT64 *)Uint8Buffer));
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (Width) {
+ case EfiPciWidthUint8:
+ *Uint8Buffer = MmioRead8 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint16:
+ *((UINT16 *)Uint8Buffer) = MmioRead16 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint32:
+ *((UINT32 *)Uint8Buffer) = MmioRead32 ((UINTN)Address);
+ break;
+ case EfiPciWidthUint64:
+ *((UINT64 *)Uint8Buffer) = MmioRead64 ((UINTN)Address);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write IO space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoIoRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ DEBUG ((DEBUG_INFO, "PCI Root Bridge Io Io Read/Write function is not implemented yet.\n"));
+ return EFI_SUCCESS;
+}
+
+/**
+ Internal help function for read and write PCI configuration space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Write Switch value for Read or Write.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in, out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+RootBridgeIoPciRW (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN BOOLEAN Write,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ INT32 Offset;
+ UINT32 BusDev;
+ UINT8 InStride;
+ UINT8 OutStride;
+ UINT8 *Uint8Buffer;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS *PciRbAddr;
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+ Status = RootBridgeIoCheckParameter (This, PciOperation, Width, Address, Count, Buffer);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ PciRbAddr = (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS*) &Address;
+
+ if (PciRbAddr->ExtendedRegister) {
+ Offset = (INT32) PciRbAddr->ExtendedRegister;
+ }
+ else {
+ Offset = (INT32) PciRbAddr->Register;
+ }
+
+ BusDev = (UINT32)PCI_BUS_DEV (
+ PciRbAddr->Bus,
+ PciRbAddr->Device,
+ PciRbAddr->Function
+ );
+
+ InStride = mInStride[Width];
+ OutStride = mOutStride[Width];
+
+ for (Uint8Buffer = Buffer; Count > 0; Offset += InStride, Uint8Buffer += OutStride, Count--) {
+ if (Write) {
+ switch (Width) {
+ case EfiPciWidthUint8:
+ Status = PcieWriteConfigByte (PrivateData, (UINT32)BusDev, Offset, *Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ Status = PcieWriteConfigWord (PrivateData, (UINT32)BusDev, Offset, *(UINT16 *)Uint8Buffer);
+ break;
+ case EfiPciWidthUint32:
+ Status = PcieWriteConfig (PrivateData, (UINT32)BusDev, Offset, *(UINT32 *)Uint8Buffer);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (Width) {
+ case EfiPciWidthUint8:
+ Status = PcieReadConfigByte (PrivateData, (UINT32)BusDev, Offset, Uint8Buffer);
+ break;
+ case EfiPciWidthUint16:
+ Status = PcieReadConfigWord (PrivateData, (UINT32)BusDev, Offset, (UINT16 *)Uint8Buffer);
+ break;
+ case EfiPciWidthUint32:
+ Status = PcieReadConfig (PrivateData, (UINT32)BusDev, Offset, (UINT32 *)Uint8Buffer);
+ break;
+ default:
+ //
+ // The RootBridgeIoCheckParameter call above will ensure that this
+ // path is not taken.
+ //
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+
+ return Status;
+}
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH edk2-platforms 2/3] Platform/NXP : Add PCI Host Bridge Driver
2017-12-21 18:48 [PATCH edk2-platforms 0/3] Platform/NXP-Added NXP PCI Host Bridge Driver Vabhav
2017-12-21 18:48 ` [PATCH edk2-platforms 1/3] Platform/NXP : Add PCI Host Bridge Libary Vabhav
@ 2017-12-21 18:48 ` Vabhav
2017-12-21 18:48 ` [PATCH edk2-platforms 3/3] Compilation:Modify dsc, fdf files Vabhav
2017-12-22 15:33 ` [PATCH edk2-platforms 0/3] Platform/NXP-Added NXP PCI Host Bridge Driver Ard Biesheuvel
3 siblings, 0 replies; 7+ messages in thread
From: Vabhav @ 2017-12-21 18:48 UTC (permalink / raw)
To: ard.biesheuvel, leif.lindholm, michael.d.kinney, edk2-devel
Added NXP PCI host bridge Dxe driver which install
host bridge resource allocation protocol,root bridge IO
protocol,Device path protocol and consumes MetronomeArch
Protocol.
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Vabhav <vabhav.sharma@nxp.com>
---
.../Drivers/PciHostBridgeDxe/PciHostBridgeDxe.c | 967 ++++++++++++++++
.../Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf | 61 +
.../NXP/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c | 1193 ++++++++++++++++++++
Platform/NXP/Include/PciHostBridge.h | 466 ++++++++
Platform/NXP/Include/PciRootBridge.h | 674 +++++++++++
5 files changed, 3361 insertions(+)
create mode 100644 Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.c
create mode 100644 Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
create mode 100644 Platform/NXP/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c
create mode 100644 Platform/NXP/Include/PciHostBridge.h
create mode 100644 Platform/NXP/Include/PciRootBridge.h
diff --git a/Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.c b/Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.c
new file mode 100644
index 0000000..e9e43bc
--- /dev/null
+++ b/Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.c
@@ -0,0 +1,967 @@
+/** PciHostBridgeDxe.c
+ Provides all functions of PCI Host Bridge Resource Allocation Protocol
+
+ Based on PCI HosttBridge implementation in
+ ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciHostBridgeResourceAllocation.c
+
+ Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PciHostBridge.h>
+
+/**
+ Hard code: Root Bridge Number within the host bridge
+ Root Bridge's attribute
+ Root Bridge's device path
+ Root Bridge's resource aperture
+**/
+
+UINT64 PciMemBase[NUM_PCIE_CONTROLLER];
+UINT64 PciBaseAddr[NUM_PCIE_CONTROLLER];
+
+PCI_HOST_BRIDGE_INSTANCE *HostBridge[NUM_PCIE_CONTROLLER];
+PCI_ROOT_BRIDGE_INSTANCE *PrivateData[NUM_PCIE_CONTROLLER];
+
+
+UINT64 RootBridgeAttribute[1][1] = { {EFI_PCI_HOST_BRIDGE_MEM64_DECODE | EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM} };
+
+EFI_PCI_ROOT_BRIDGE_DEVICE_PATH mEfiPciRootBridgeDevicePath = {
+ {
+ { ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8) (sizeof (ACPI_HID_DEVICE_PATH)),
+ (UINT8) ((sizeof (ACPI_HID_DEVICE_PATH)) >> 8)
+ }
+ },
+ EISA_PNP_ID (0x0A03),
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+};
+
+EFI_HANDLE mPciDriverImageHandle;
+
+PCI_HOST_BRIDGE_INSTANCE gPciHostBridgeInstanceTemplate = {
+ PCI_HOST_BRIDGE_SIGNATURE, // Signature
+ NULL, // HostBridgeHandle
+ NULL, // ImageHandle
+ {0, 0, 0, 0}, // RootBridgeNumber
+ NULL, // RootBridgeInstance
+ {NULL, NULL}, // Head
+ FALSE, // ResourceSubiteed
+ TRUE, // CanRestarted
+ { // ResAlloc
+ PciNotifyPhase,
+ PciGetNextRootBridge,
+ PciGetAllocAttributes,
+ PciStartBusEnumeration,
+ PciSetBusNumbers,
+ PciSubmitResources,
+ PciGetProposedResources,
+ PciPreprocessController
+ }
+};
+
+/**
+ This function checks whether PCIe is enabled or not
+ depending upon board serdes protocol map
+
+ @param PcieNum PCIe number
+
+ @return The PCIe number enabled in map
+ @return FALSE PCIe number is disabled in map
+**/
+STATIC
+BOOLEAN
+IsPcieNumEnabled(
+ IN UINTN PcieNum
+ )
+{
+ UINT64 SerDes1ProtocolMap;
+
+ SerDes1ProtocolMap = 0x0;
+
+ GetSerdesProtocolMaps (&SerDes1ProtocolMap);
+
+ if (PcieNum < NUM_PCIE_CONTROLLER) {
+ return IsSerDesLaneProtocolConfigured (SerDes1ProtocolMap, (PcieNum+1));
+ }
+ else {
+ DEBUG ((DEBUG_ERROR, "Device not supported\n"));
+ }
+
+ return FALSE;
+}
+
+STATIC
+EFI_STATUS
+AddMemorySpace (
+ IN UINT64 BaseAddress,
+ IN UINTN Size
+ )
+{
+ EFI_STATUS Status;
+ Status = gDS->AddMemorySpace (
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BaseAddress,
+ Size,
+ 0
+ );
+
+ return Status;
+}
+
+/**
+ Entry point of this driver
+
+ @param ImageHandle Handle of driver image
+ @param SystemTable Point to EFI_SYSTEM_TABLE
+
+ @retval EFI_ABORTED PCI host bridge not present
+ @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
+ @retval EFI_DEVICE_ERROR Can not install the protocol instance
+ @retval EFI_SUCCESS Success to initialize the Pci host bridge.
+**/
+EFI_STATUS
+EFIAPI
+PciHostBridgeEntryPoint (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ UINTN Loop1;
+
+ Status = EFI_OUT_OF_RESOURCES; // error
+
+ for (Loop1 = 0; Loop1 < NUM_PCIE_CONTROLLER; Loop1++) {
+ PciMemBase[Loop1] = PcdGet64 (PcdPci1Mmio64Base) +
+ (PCI_MMIO64_BASE_DIFFERENCE * Loop1);
+ PciBaseAddr[Loop1] = PcdGet64 (PcdPciExp1BaseAddr) +
+ (PcdGet64 (PcdPciExp1BaseSize) * Loop1);
+
+ DEBUG ((DEBUG_INFO, "PciMemBase %d : 0x%p\n", Loop1, PciMemBase[Loop1]));
+ DEBUG ((DEBUG_INFO, "PciBaseAddr %d : 0x%p\n", Loop1, PciBaseAddr[Loop1]));
+ }
+
+ //
+ // Create Host Bridge Device Handle
+ //
+ for (Loop1 = 0; Loop1 < NUM_PCIE_CONTROLLER; Loop1++) {
+ if (!IsPcieNumEnabled (Loop1)) {
+ DEBUG ((DEBUG_ERROR, "PCIE%d is disabled\n", (Loop1 + 1)));
+ continue;
+ }
+
+ DEBUG ((DEBUG_INFO, "PCIE%d is Enabled\n", (Loop1 + 1)));
+
+ HostBridge[Loop1] = AllocateCopyPool (sizeof (PCI_HOST_BRIDGE_INSTANCE), &gPciHostBridgeInstanceTemplate);
+ if (HostBridge[Loop1] == NULL) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to Allocate HostBridge: %d\n", Loop1));
+ continue; // Continue with other controllers
+ }
+
+ HostBridge[Loop1]->RootBridgeNumber[Loop1] = TRUE;
+ InitializeListHead (&HostBridge[Loop1]->Head);
+ DEBUG ((DEBUG_INFO, "PCI : Install Protocol for HostBridge: %d\n", Loop1));
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &HostBridge[Loop1]->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge[Loop1]->ResAlloc,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "%a: Fail to install resource alloc\n", __FUNCTION__));
+ FreePool (HostBridge[Loop1]);
+ continue; // Continue with other controllers
+ } else {
+ DEBUG ((DEBUG_INFO, "%a: Succeed to install resource allocation protocol\n", __FUNCTION__));
+ }
+
+ HostBridge[Loop1]->ImageHandle = ImageHandle;
+ //
+ // Create Root Bridge Device Handle in this Host Bridge
+ //
+ PrivateData[Loop1] = AllocateZeroPool (sizeof (PCI_ROOT_BRIDGE_INSTANCE));
+ if (PrivateData[Loop1] == NULL) {
+ gBS->UninstallMultipleProtocolInterfaces (
+ HostBridge[Loop1]->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge[Loop1]->ResAlloc,
+ NULL
+ ); // Uninstall Resource Allocation protocol
+ FreePool (HostBridge[Loop1]); // Unallocate previous memory,
+ continue; // Continue with other controllers
+ }
+
+ PrivateData[Loop1]->Signature = PCI_ROOT_BRIDGE_SIGNATURE;
+ CopyMem (&(PrivateData[Loop1]->DevicePath), &mEfiPciRootBridgeDevicePath, sizeof (EFI_PCI_ROOT_BRIDGE_DEVICE_PATH));
+ // Set Device Path for this Root Bridge
+
+ PrivateData[Loop1]->DevicePath.AcpiDevicePath.UID = Loop1;
+ PrivateData[Loop1]->PciMemBase64 = PciMemBase[Loop1];
+
+ PrivateData[Loop1]->Info = AllocateZeroPool (sizeof (LsPcieInfo));
+ PrivateData[Loop1]->Pcie = AllocateZeroPool (sizeof (LsPcie));
+
+ SetLSPcieInfo(PrivateData[Loop1]->Info, (Loop1+1));
+
+ HostBridge[Loop1]->RootBridge = PrivateData[Loop1];
+
+ if (FeaturePcdGet (PcdPciDebug) == TRUE) {
+ DEBUG ((DEBUG_INFO, "Installed Host Bridges successfully\n"));
+ }
+
+ Status = PciRbInitialize (
+ PrivateData[Loop1],
+ (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *)&PrivateData[Loop1]->Io,
+ PrivateData[Loop1]->Info,
+ HostBridge[Loop1]->HostBridgeHandle,
+ RootBridgeAttribute[0][0],
+ (Loop1+1),
+ 0,
+ PciBaseAddr
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->UninstallMultipleProtocolInterfaces (
+ HostBridge[Loop1]->HostBridgeHandle,
+ &gEfiPciHostBridgeResourceAllocationProtocolGuid, &HostBridge[Loop1]->ResAlloc,
+ NULL
+ );
+
+ FreePool (PrivateData[Loop1]->Info);
+ FreePool (PrivateData[Loop1]->Pcie);
+ FreePool (PrivateData[Loop1]);
+ FreePool (HostBridge[Loop1]);
+ DEBUG ((DEBUG_INFO, "UNInstalled HostBridge ResAlloc protocol and Freed memory\n"));
+ continue; // Continue with other controllers
+ }
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &PrivateData[Loop1]->Handle,
+ &gEfiDevicePathProtocolGuid, &PrivateData[Loop1]->DevicePath,
+ &gEfiPciRootBridgeIoProtocolGuid, &PrivateData[Loop1]->Io,
+ NULL
+ );
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Failed to install RootBridgeIo and DevicePath protocols\n"));
+ FreePool (PrivateData[Loop1]);
+ return EFI_DEVICE_ERROR;
+ }
+
+ DEBUG ((DEBUG_INFO, "Successfully Installed RootBridgeIo and DevicePath protocols\n"));
+ InsertTailList (&HostBridge[Loop1]->Head, &PrivateData[Loop1]->Link);
+ Status = AddMemorySpace (PciMemBase[Loop1], PCI_MEM64_SIZE);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((DEBUG_ERROR, "Memory Resource couldn't be added for PCI%d_MEM64\n",Loop1));
+ return EFI_DEVICE_ERROR;
+ }
+
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Functions declarations for Host Bridge Resource allocation protocol
+
+ @param ImageHandle Handle of driver image
+ @param SystemTable Point to EFI_SYSTEM_TABLE
+
+ @retval EFI_ABORTED PCI host bridge not present
+ @retval EFI_OUT_OF_RESOURCES Can not allocate memory resource
+ @retval EFI_DEVICE_ERROR Can not install the protocol instance
+ @retval EFI_SUCCESS Success to initialize the Pci host bridge.
+**/
+EFI_STATUS
+PciNotifyPhase (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS BaseAddress;
+ UINT64 AddrLen;
+ UINTN BitsOfAlignment;
+
+ BaseAddress = 0x0;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+
+ // Check RootBridge Signature
+ ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
+
+ // The enumeration cannot be restarted after the process has been further than the first phase
+ if (Phase == EfiPciHostBridgeBeginEnumeration) {
+ if (!HostBridgeInstance->CanRestarted) {
+ return EFI_NOT_READY;
+ }
+ } else {
+ HostBridgeInstance->CanRestarted = FALSE;
+ }
+
+ switch (Phase) {
+ case EfiPciHostBridgeBeginEnumeration:
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ break;
+
+ case EfiPciHostBridgeBeginBusAllocation:
+ // The bus allocation phase is about to begin
+ break;
+
+ case EfiPciHostBridgeEndBusAllocation:
+ // The bus allocation and bus programming phase is complete. All the PCI-to-PCI bridges have been given and written back
+ // a bus number range into their configuration
+ break;
+
+ case EfiPciHostBridgeBeginResourceAllocation:
+ // The resource allocation phase is about to begin.
+ break;
+
+ case EfiPciHostBridgeAllocateResources:
+ // Allocates resources per previously submitted requests for all the PCI root bridges. The resources have been submitted to
+ // PciHbRaSubmitResources() before.
+
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ if (RootBridgeInstance->ResAlloc[ResTypeIo].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeIo].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypeIo].Length;
+
+ Status = gDS->AllocateIoSpace (
+ EfiGcdAllocateAnySearchBottomUp,
+ EfiGcdIoTypeIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+ // If error then ResAlloc[n].Base ==0
+ if (!EFI_ERROR (Status)) {
+ RootBridgeInstance->ResAlloc[ResTypeIo].Base = (UINTN)BaseAddress;
+ }
+ }
+
+ if (RootBridgeInstance->ResAlloc[ResTypeMem32].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem32].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem32].Length;
+
+ // Top of the 64bit PCI Memory space
+ BaseAddress = RootBridgeInstance->PciMemBase64 + PCI_MEM64_SIZE;
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 64bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= RootBridgeInstance->PciMemBase64)) {
+ RootBridgeInstance->ResAlloc[ResTypeMem32].Base = (UINTN)(BaseAddress - RootBridgeInstance->PciBaseAddress64);
+ }
+ }
+
+ if (RootBridgeInstance->ResAlloc[ResTypePMem32].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem32].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem32].Length;
+
+ // Top of the 64bit PCI Memory space
+ BaseAddress = RootBridgeInstance->PciMemBase64 + PCI_MEM64_SIZE;
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 64bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= RootBridgeInstance->PciMemBase64)) {
+ RootBridgeInstance->ResAlloc[ResTypePMem32].Base = (UINTN)(BaseAddress - RootBridgeInstance->PciBaseAddress64);
+ }
+ }
+
+ if (RootBridgeInstance->ResAlloc[ResTypeMem64].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypeMem64].Alignment) + 1; // Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypeMem64].Length;
+ // Top of the 64bit PCI Memory space
+ BaseAddress = RootBridgeInstance->PciMemBase64 + PCI_MEM64_SIZE;
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 64bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= RootBridgeInstance->PciMemBase64)) {
+ RootBridgeInstance->ResAlloc[ResTypeMem64].Base = (UINTN)(BaseAddress - RootBridgeInstance->PciBaseAddress64);
+ }
+ }
+ if (RootBridgeInstance->ResAlloc[ResTypePMem64].Length != 0) {
+ BitsOfAlignment = HighBitSet64 (RootBridgeInstance->ResAlloc[ResTypePMem64].Alignment) + 1; //Get the number of '1' in Alignment
+ AddrLen = RootBridgeInstance->ResAlloc[ResTypePMem64].Length;
+ // Top of the 64bit PCI Memory space
+ BaseAddress = RootBridgeInstance->PciMemBase64 + PCI_MEM64_SIZE;
+
+ Status = gDS->AllocateMemorySpace (
+ EfiGcdAllocateMaxAddressSearchTopDown,
+ EfiGcdMemoryTypeMemoryMappedIo,
+ BitsOfAlignment,
+ AddrLen,
+ &BaseAddress,
+ HostBridgeInstance->ImageHandle,
+ NULL
+ );
+
+ // Ensure the allocation is in the 64bit PCI memory space
+ if (!EFI_ERROR (Status) && (BaseAddress >= RootBridgeInstance->PciMemBase64)) {
+ RootBridgeInstance->ResAlloc[ResTypePMem64].Base = (UINTN)(BaseAddress - RootBridgeInstance->PciBaseAddress64);
+ }
+ }
+
+ break;
+
+ case EfiPciHostBridgeSetResources:
+ // Programs the host bridge hardware to decode previously allocated resources (proposed resources)
+ // for all the PCI root bridges. The PCI bus driver will now program the resources
+ break;
+
+ case EfiPciHostBridgeFreeResources:
+ // Deallocates resources that were previously allocated for all the PCI root bridges and resets the
+ // I/O and memory apertures to their initial state.*/
+ break;
+
+ case EfiPciHostBridgeEndResourceAllocation:
+ break;
+
+ case EfiPciHostBridgeEndEnumeration:
+ break;
+
+ default:
+ DEBUG ((DEBUG_INFO, "PciHbRaNotifyPhase (Phase:%d)\n", Phase));
+ ASSERT (0);
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ This function returns the next root bridge attached to the
+ 'This' PCI Host Bridge.
+ There is only one PCI Root Bridge in this PCI interface, we
+ return either this root bridge if it the first time we call
+ this function (*RootBridgeHandle == NULL) or return EFI_NOT_FOUND
+ **/
+EFI_STATUS
+PciGetNextRootBridge (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ ASSERT (HostBridgeInstance->RootBridge != NULL);
+
+ //Check RootBridge Signature
+ ASSERT (HostBridgeInstance->RootBridge->Signature == PCI_ROOT_BRIDGE_SIGNATURE);
+
+ if (*RootBridgeHandle == NULL) {
+ *RootBridgeHandle = HostBridgeInstance->RootBridge->Handle;
+ return EFI_SUCCESS;
+ } else if (*RootBridgeHandle == HostBridgeInstance->RootBridge->Handle) {
+ return EFI_NOT_FOUND;
+ } else {
+ return EFI_INVALID_PARAMETER;
+ }
+}
+
+/**
+ This function returns the resource allocation attributes supported
+ by this PCI Root Bridge.
+ A PCI Root bridge could support these types :
+ - EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM : does not support separate
+ windows for nonprefetchable and prefetchable memory.
+ - EFI_PCI_HOST_BRIDGE_MEM64_DECODE : supports 64-bit memory windows
+
+ @param This Pointer to host bridge resource allocation protocol
+
+ @return Attributes Attribues supported by the PCI root bridge
+ **/
+EFI_STATUS
+PciGetAllocAttributes (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ // Check if the RootBridgeHandle is the one managed by this PCI Host Bridge
+ ASSERT (HostBridgeInstance->RootBridge != NULL);
+ if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *Attributes = HostBridgeInstance->RootBridge->RootBridgeAttrib;
+ return EFI_SUCCESS;
+}
+
+/**
+
+ This function sets up the specified PCI root bridge for the
+ bus enumeration process
+
+ @param This pointer to host bridge resource allocation protocol
+**/
+EFI_STATUS
+PciStartBusEnumeration (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ VOID *Buffer;
+ UINT8 *Ptr;
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ Buffer = AllocateZeroPool (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = (UINT8 *)Buffer;
+
+ // Fill an ACPI descriptor table with the Bus Number Range. This information will be used by the PCI Bus driver
+ // to set bus numbers to PCI-to-PCI bridge.
+
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR; // QWORD Address space Descriptor
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->Len = 0x2B; // Length of this descriptor in bytes not including the first two fields
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType = ACPI_ADDRESS_SPACE_TYPE_BUS; // Resource Type Bus Number Range
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->GenFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->SpecificFlag = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrSpaceGranularity = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin = HostBridgeInstance->RootBridge->BusStart; // Bus Start
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMax = 0; // Bus Max
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrTranslationOffset = 0;
+ ((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
+
+ Ptr = Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function set PCI bus number(start,end for this root bridge instance
+ -Checks if ACPI descriptor is passed for supported bus range
+**/
+EFI_STATUS
+PciSetBusNumbers (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ UINT8 *Ptr;
+ UINTN BusStart;
+ UINTN BusEnd;
+ UINTN BusLen;
+
+ Ptr = Configuration;
+ if (*Ptr != ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the passed ACPI descriptor table define a Bus Number Range
+ if (((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->ResType != ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the Configuration only passed one ACPI Descriptor (+ End Descriptor)
+ if (*((UINT8*)(Ptr + sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR))) != ACPI_END_TAG_DESCRIPTOR) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ ASSERT (HostBridgeInstance->RootBridge != NULL);
+ if (HostBridgeInstance->RootBridge->Handle != RootBridgeHandle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BusStart = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrRangeMin;
+ BusLen = (UINTN)((EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr)->AddrLen;
+ BusEnd = BusStart + BusLen - 1;
+
+ ASSERT (BusStart <= BusEnd); // We should at least have PCI_BUS_ROOT and PCI_SWITCH_BUS
+ ASSERT ((BusStart >= HostBridgeInstance->RootBridge->BusStart) && (BusLen <= HostBridgeInstance->RootBridge->BusLength));
+
+ HostBridgeInstance->RootBridge->BusStart = BusStart;
+ HostBridgeInstance->RootBridge->BusLength = BusLen;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function is used to submit all the I/O and memory resources
+ that are required by the specified PCI root bridge.
+ **/
+EFI_STATUS
+PciSubmitResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT8 *Ptr;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+ PCI_RESOURCE_TYPE ResType;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ if (Configuration == NULL) {
+ DEBUG((DEBUG_ERROR, "PciHbRaSubmitResources(): NULL COnf\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check if the ACPI Descriptor tables is conformed
+ Ptr = (UINT8 *)Configuration;
+ while (*Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // QWORD Address Space descriptor
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) ;
+ }
+ if (*Ptr != ACPI_END_TAG_DESCRIPTOR) { // End tag
+ DEBUG ((DEBUG_ERROR, "PciHbRaSubmitResources(): END tag issue\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Check the RootBridgeHandle
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ ASSERT (RootBridgeInstance != NULL);
+ if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
+ DEBUG ((DEBUG_ERROR, "PciHbRaSubmitResources(): HB/RB dont match\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Ptr = (UINT8 *)Configuration;
+ while ( *Ptr == ACPI_ADDRESS_SPACE_DESCRIPTOR) { // While the entry is an ACPI Descriptor Table
+ Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+
+ // Check if the description is valid
+ if (Desc->AddrLen > 0xffffffff) {
+ DEBUG ((DEBUG_ERROR, "PciHbRaSubmitResources(): Invalid addr length\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Desc->AddrRangeMax >= 0xffffffff) || (Desc->AddrRangeMax != (GetPowerOfTwo64 (Desc->AddrRangeMax + 1) - 1))) {
+ DEBUG ((DEBUG_ERROR, "PciHbRaSubmitResources(): Invalid addr range\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ switch (Desc->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+ // Check invalid Address Space Granularity
+ if ((Desc->AddrSpaceGranularity != 32) && (Desc->AddrSpaceGranularity != 64)) {
+ DEBUG ((DEBUG_ERROR, "PciHbRaSubmitResources(): Invalid addr space granul\n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // check the memory resource request is supported by PCI root bridge
+ if (RootBridgeInstance->MemAllocAttributes == EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM && Desc->SpecificFlag == 0x06) {
+ DEBUG ((DEBUG_ERROR, "PciHbRaSubmitResources(): Invalid memalloc attri \n"));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Desc->AddrSpaceGranularity == 32) {
+ if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
+ ResType = ResTypePMem32;
+ } else {
+ ResType = ResTypeMem32;
+ }
+ } else {
+ if (Desc->SpecificFlag == ACPI_SPECFLAG_PREFETCHABLE) {
+ ResType = ResTypePMem64;
+ } else {
+ ResType = ResTypeMem64;
+ }
+ }
+ RootBridgeInstance->ResAlloc[ResType].Length = Desc->AddrLen;
+ RootBridgeInstance->ResAlloc[ResType].Alignment = Desc->AddrRangeMax;
+ RootBridgeInstance->ResAlloc[ResType].Base = Desc->AddrRangeMin;
+ break;
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+ RootBridgeInstance->ResAlloc[ResTypeIo].Length = Desc->AddrLen;
+ RootBridgeInstance->ResAlloc[ResTypeIo].Alignment = Desc->AddrRangeMax;
+ RootBridgeInstance->ResAlloc[ResTypeIo].Base = 0;
+ break;
+ default:
+ ASSERT (0); // Could be the case Desc->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS
+ break;
+ }
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ This function Returns the proposed resource settings for the specified
+ PCI root bridge. The resources have been submitted by
+ PciHbRaSubmitResources()
+
+ @param This Pointer to host bridge resource allocation
+ instance
+ @param RootBridgeHandle Pointer to this root bridge instance
+
+ @return Configuration Pointer to resource settings
+ @return EFI_SUCCESS Successful returned requested resource
+ settings
+ @return EFI_INVALID_PARAMETER Invalid parameter for root bridge
+ @return EFI_OUT_OF_RESOURCES Resources can not be allocated
+ **/
+EFI_STATUS
+PciGetProposedResources (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE *HostBridgeInstance;
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridgeInstance;
+ UINT32 i;
+ UINT32 ResAllocCount;
+ VOID *Buffer;
+ UINT8 *Ptr;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Desc;
+
+ HostBridgeInstance = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+
+ // Check the RootBridgeHandle
+ RootBridgeInstance = HostBridgeInstance->RootBridge;
+ ASSERT (RootBridgeInstance != NULL);
+ if (RootBridgeHandle != HostBridgeInstance->RootBridge->Handle) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // Count the number of Resource Allocated for this Root Bridge
+ ResAllocCount = 0;
+ for (i = 0; i < ResTypeMax; i++) {
+ if (RootBridgeInstance->ResAlloc[i].Length != 0) ResAllocCount++;
+ }
+
+ if (ResAllocCount == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Buffer = AllocateZeroPool (ResAllocCount * sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) + sizeof (EFI_ACPI_END_TAG_DESCRIPTOR));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = Buffer;
+ for (i = 0; i < ResTypeMax; i++) {
+ // Base != 0 if the resource has been allocated
+ if (RootBridgeInstance->ResAlloc[i].Length != 0) {
+ Desc = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)Ptr;
+
+ Desc->Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
+ Desc->Len = 0x2B;
+ Desc->GenFlag = 0;
+ Desc->AddrRangeMax = 0;
+
+ switch (i) {
+ case ResTypeIo:
+ Desc->Desc = 0x8A;
+ Desc->Len = 0x2B;
+ Desc->ResType = 1;
+ Desc->GenFlag = 0;
+ Desc->SpecificFlag = 0;
+ Desc->AddrSpaceGranularity = 0;
+ Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
+ Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
+ break;
+ case ResTypeMem32:
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->Desc = 0x8A;
+ Desc->Len = 0x2B;
+ Desc->ResType = 0;
+ Desc->GenFlag = 0;
+ Desc->SpecificFlag = 0;
+ Desc->AddrSpaceGranularity = 32;
+ Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
+ Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
+ break;
+ case ResTypePMem32:
+ Desc->Desc = 0x8A;
+ Desc->Len = 0x2B;
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->GenFlag = 0;
+ Desc->SpecificFlag = 6;
+ Desc->AddrSpaceGranularity = 32;
+ Desc->AddrRangeMin = 0;
+ Desc->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Desc->AddrLen = 0;
+ break;
+ case ResTypeMem64:
+ Desc->Desc = 0x8A;
+ Desc->Len = 0x2B;
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->GenFlag = 0;
+ Desc->SpecificFlag = 0;
+ Desc->AddrSpaceGranularity = 64;
+ Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
+ Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
+ break;
+ case ResTypePMem64:
+ Desc->Desc = 0x8A;
+ Desc->Len = 0x2B;
+ Desc->ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
+ Desc->GenFlag = 0;
+ Desc->SpecificFlag = 6;
+ Desc->AddrSpaceGranularity = 64;
+ Desc->AddrRangeMin = 0;
+ Desc->AddrTranslationOffset = EFI_RESOURCE_NONEXISTENT;
+ Desc->AddrLen = 0;
+ break;
+ }
+ Desc->AddrRangeMin = RootBridgeInstance->ResAlloc[i].Base;
+ Desc->AddrTranslationOffset = EFI_RESOURCE_SATISFIED;
+ Desc->AddrLen = RootBridgeInstance->ResAlloc[i].Length;
+ Ptr += sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR);
+ }
+ }
+
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Desc = ACPI_END_TAG_DESCRIPTOR;
+ ((EFI_ACPI_END_TAG_DESCRIPTOR *)Ptr)->Checksum = 0x0;
+
+ *Configuration = Buffer;
+ return EFI_SUCCESS;
+}
+
+/**
+ This function allow the host bridge driver to preinitialize individual
+ PCI controllers before enumeration
+**/
+EFI_STATUS
+PciPreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ )
+{
+ PCI_HOST_BRIDGE_INSTANCE* HostBridge;
+ PCI_ROOT_BRIDGE_INSTANCE* RootBridge;
+ UINT32 CapabilityPtr;
+ UINT32 CapabilityEntry;
+ UINT16 CapabilityID;
+ UINT32 DeviceCapability;
+
+ if (FeaturePcdGet (PcdPciMaxPayloadFixup)) {
+ // Do Max payload fixup for every devices
+ if (Phase == EfiPciBeforeResourceCollection) {
+ // Get RootBridge Instance from Host Bridge Instance
+ HostBridge = INSTANCE_FROM_RESOURCE_ALLOCATION_THIS (This);
+ RootBridge = HostBridge->RootBridge;
+
+ // Get the first PCI Capability
+ CapabilityPtr = PCI_CAPBILITY_POINTER_OFFSET;
+ RootBridge->Io.Pci.Read (
+ &RootBridge->Io,
+ EfiPciWidthUint8,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
+ 1,
+ &CapabilityPtr
+ );
+ CapabilityPtr &= 0x1FF;
+
+ // Get Pci Express Capability
+ while (CapabilityPtr != 0) {
+ RootBridge->Io.Pci.Read (
+ &RootBridge->Io,
+ EfiPciWidthUint16,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr),
+ 1,
+ &CapabilityEntry
+ );
+
+ CapabilityID = (UINT8)CapabilityEntry;
+
+ // Is PCIe capability ?
+ if (CapabilityID == EFI_PCI_CAPABILITY_ID_PCIEXP) {
+ // Get PCIe Device Capabilities
+ RootBridge->Io.Pci.Read (
+ &RootBridge->Io,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
+ 1,
+ &DeviceCapability
+ );
+
+ // Force the Max Payload to 128 Bytes (128 Bytes Max Payload Size = 0)
+ DeviceCapability &= ~ ((UINT32)(0x7 << 5 ));
+ // Max Read Request Size to 128 Bytes (128 Bytes Max Read Request Size = 0)
+ DeviceCapability &= ~ ((UINT32)(0x7 << 12));
+ // Enable all error reporting
+ DeviceCapability |= 0xF;
+
+ RootBridge->Io.Pci.Write (
+ &RootBridge->Io,
+ EfiPciWidthUint32,
+ EFI_PCI_ADDRESS (PciAddress.Bus, PciAddress.Device, PciAddress.Function, CapabilityPtr + 0x8),
+ 1,
+ &DeviceCapability
+ );
+
+ return EFI_SUCCESS;
+ }
+ CapabilityPtr = (CapabilityEntry >> 8) & 0xFF;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
diff --git a/Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf b/Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
new file mode 100644
index 0000000..019cc63
--- /dev/null
+++ b/Platform/NXP/Drivers/PciHostBridgeDxe/PciHostBridgeDxe.inf
@@ -0,0 +1,61 @@
+/* PciHostBridgeDxe.inf
+#
+# Component description file for PCI Host Bridge driver
+#
+# Copyright (c) 2015, Freescale Semiconductor, Inc. All rights reserved.
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+*/
+
+[Defines]
+ INF_VERSION = 0x0001001A
+ BASE_NAME = PciHostBridge
+ FILE_GUID = C62F4B20-681E-11DF-8F0D-0002A5D5C51B
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = PciHostBridgeEntryPoint
+
+[Packages]
+ MdePkg/MdePkg.dec
+ Platform/NXP/NxpQoriqLs.dec
+ Silicon/NXP/Chassis/Chassis2/Chassis2.dec
+
+[LibraryClasses]
+ DxeServicesTableLib
+ PciHostBridgeLib
+ SocLib
+ UefiDriverEntryPoint
+
+[Sources]
+ PciHostBridgeDxe.c
+ PciRootBridgeIo.c
+
+[FixedPcd]
+ gNxpQoriqLsTokenSpaceGuid.PcdPciBusMin
+ gNxpQoriqLsTokenSpaceGuid.PcdPciBusMax
+ gNxpQoriqLsTokenSpaceGuid.PcdPci1Mmio64Base
+ gNxpQoriqLsTokenSpaceGuid.PcdPciMmio64Size
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
+ gNxpQoriqLsTokenSpaceGuid.PcdKludgeMapPciMmioAsCached
+ gNxpQoriqLsTokenSpaceGuid.PcdPciMaxPayloadFixup
+ gNxpQoriqLsTokenSpaceGuid.PcdPciDebug
+ gNxpQoriqLsTokenSpaceGuid.PcdNumPciController
+ gNxpQoriqLsTokenSpaceGuid.PcdPciMemOneTransaction
+ gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseSize
+
+[Protocols]
+ gEfiPciHostBridgeResourceAllocationProtocolGuid ## PRODUCES
+ gEfiPciRootBridgeIoProtocolGuid ## PRODUCES
+ gEfiMetronomeArchProtocolGuid ## CONSUMES
+ gEfiDevicePathProtocolGuid ## PRODUCES
+
+[Depex]
+ TRUE
diff --git a/Platform/NXP/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c b/Platform/NXP/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c
new file mode 100644
index 0000000..9a5c238
--- /dev/null
+++ b/Platform/NXP/Drivers/PciHostBridgeDxe/PciRootBridgeIo.c
@@ -0,0 +1,1193 @@
+/** PciRootBridgeIo.c
+ PCI Root Bridge Io Protocol implementation
+
+ Based on PCI RootBridge implementation in
+ ArmPlatformPkg/ArmJunoPkg/Drivers/PciHostBridgeDxe/PciRootBridge.c
+
+ Copyright (c) 2011-2015, ARM Ltd. All rights reserved.
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <PciHostBridge.h>
+
+typedef struct {
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR SpaceDesp[ResTypeMax+1];
+ EFI_ACPI_END_TAG_DESCRIPTOR EndDesp;
+} RESOURCE_CONFIGURATION;
+
+RESOURCE_CONFIGURATION Configuration = {
+ {{ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_IO , 0, 0, 0, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 32, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 32, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 0, 64, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_MEM, 0, 6, 64, 0, 0, 0, 0},
+ {ACPI_ADDRESS_SPACE_DESCRIPTOR, 0x2B, ACPI_ADDRESS_SPACE_TYPE_BUS, 0, 0, 0, 0, 255, 0, 255}},
+ {ACPI_END_TAG_DESCRIPTOR, 0}
+};
+
+//
+// Memory Controller Pci Root Bridge Io Module Variables
+//
+EFI_METRONOME_ARCH_PROTOCOL *mMetronome;
+
+/**
+
+ Initialize and create Pci Root Bridges for Board
+
+ @param PrvateData Driver instance of this Root Bridge IO protocol
+ @param Protocol Point to protocol instance
+ @param Info Point to Info field of this driver instance
+ @param HostBridgeHandle Handle of host bridge
+ @param Attri Attribute of host bridge
+ @param HostNo HostNo for this Host Bridge
+ @param Busno Bus Number for the Host Bridge
+
+ @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+
+**/
+EFI_STATUS
+PciRbInitialize (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN LsPcieInfo *Info,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN INTN HostNo,
+ IN INTN Busno,
+ IN UINT64 *PciBaseAddr
+ )
+{
+ EFI_STATUS Status;
+ LsPcie *Pcie;
+ PciDevT Pdev;
+ INTN LinkUp, EpMode;
+ UINT8 HeaderType;
+ UINT16 Temp16;
+ UINT16 VendorID16;
+ UINT16 DeviceID16;
+ UINT16 Cntr;
+
+ Pdev = ((Busno) << 16 | (0) << 11 | (0) << 8);
+ Pcie = PrivateData->Pcie;
+
+ PrivateData->FirstBusno = Busno;
+ PrivateData->Pcie->Dbi = (VOID *)Info->Regs;
+ PrivateData->Pcie->VaCfg0 = (VOID *)Info->Cfg0Phys;
+ PrivateData->Pcie->VaCfg1 = (VOID *)Info->Cfg1Phys;
+
+ LinkUp = PcieLinkUp(Pcie);
+
+ if (!LinkUp) {
+ // Let the user know there's no PCIe link
+ DEBUG ((DEBUG_INFO,"no link, regs @ 0x%lx\n", Info->Regs));
+ PrivateData->LastBusno = PrivateData->FirstBusno;
+ return EFI_ABORTED;
+ }
+ DEBUG ((DEBUG_INFO, "Passed Linkup Phase\n"));
+
+ // outbound memory
+ PciSetRegion (&PrivateData->Regions[0],
+ (PciSizeT)Info->MemBus,
+ (PhysSizeT)Info->MemPhys,
+ (PciSizeT)Info->MemSize,
+ LS_PCI_REGION_MEM);
+
+ // outbound io
+ PciSetRegion (&PrivateData->Regions[1],
+ (PciSizeT)Info->IoBus,
+ (PhysSizeT)Info->IoPhys,
+ (PciSizeT)Info->IoSize,
+ LS_PCI_REGION_IO);
+
+ // System memory space
+ PciSetRegion (&PrivateData->Regions[2],
+ LS_PCI_MEMORY_BUS,
+ LS_PCI_MEMORY_PHYS,
+ LS_PCI_MEMORY_SIZE,
+ LS_PCI_REGION_SYS_MEMORY);
+
+ PrivateData->RegionCnt = 3;
+
+ if (FeaturePcdGet (PcdPciDebug) == TRUE) {
+ for (Cntr = 0; Cntr < PrivateData->RegionCnt; Cntr++) {
+ DEBUG ((DEBUG_INFO, "PCI reg:%d %016llx:%016llx %016llx %08lx\n",
+ Cntr,
+ (UINT64)PrivateData->Regions[Cntr].PhysStart,
+ (UINT64)PrivateData->Regions[Cntr].BusStart,
+ (UINT64)PrivateData->Regions[Cntr].Size,
+ PrivateData->Regions[Cntr].Flags));
+ }
+ }
+
+ PcieReadConfigWord (PrivateData, Pdev, LS_PCI_VENDOR_ID, (UINT16 *)&VendorID16);
+ DEBUG ((DEBUG_INFO,"PCIe:VendorID: %04lx\n", VendorID16));
+ PcieReadConfigWord (PrivateData, Pdev, LS_PCI_DEVICE_ID, (UINT16 *)&DeviceID16);
+ DEBUG ((DEBUG_INFO,"PCIe Device ID: %04lx\n", DeviceID16));
+ PcieReadConfigByte (PrivateData, Pdev, LS_PCI_HEADER_TYPE, (UINT8 *)&HeaderType);
+ DEBUG ((DEBUG_INFO,"PCIe Header Type: %02lx\n", HeaderType));
+ EpMode = (HeaderType & 0x7f) == LS_PCI_HEADER_TYPE_NORMAL;
+ DEBUG ((DEBUG_INFO,"EpMode: %d\n", EpMode));
+ DEBUG ((DEBUG_INFO,"PCIe%d: %a\n", (UINT64)Info->PciNum, EpMode ? "Endpoint" : "Root Complex"));
+
+ // Print the negotiated PCIe link width
+ PcieReadConfigWord (PrivateData, Pdev, LS_PCIE_LINK_STA, (UINT16 *)&Temp16);
+ DEBUG ((DEBUG_INFO,"PCIe Link Status: %04lx\n", Temp16));
+ DEBUG ((DEBUG_INFO,"x%d gen%d, regs @ 0x%lx\n", (Temp16 & 0x3f0) >> 4,
+ (Temp16 & 0xf), Info->Regs));
+
+ if (EpMode) {
+ DEBUG ((DEBUG_INFO, "EpMode: %d\n", Busno));
+ return Busno;
+ }
+
+ PrivateData->PciBaseAddress64 = PciBaseAddr[HostNo - 1];
+ if (!PrivateData->PciBaseAddress64) {
+ DEBUG ((DEBUG_ERROR, "%a: PCI %d host bridge not present\n", __FUNCTION__, HostNo));
+ return EFI_ABORTED;
+ }
+
+ PcieSetupCntrl (PrivateData, PrivateData->Pcie, PrivateData->Info);
+
+ PrivateData->BusStart = FixedPcdGet32 (PcdPciBusMin);
+ PrivateData->BusLength = FixedPcdGet32 (PcdPciBusMax) - FixedPcdGet32 (PcdPciBusMin) + 1;
+
+ PrivateData->RootBridgeAttrib = Attri;
+
+ PrivateData->Supports = EFI_PCI_ATTRIBUTE_IDE_PRIMARY_IO | EFI_PCI_ATTRIBUTE_IDE_SECONDARY_IO | \
+ EFI_PCI_ATTRIBUTE_ISA_IO_16 | EFI_PCI_ATTRIBUTE_ISA_MOTHERBOARD_IO | \
+ EFI_PCI_ATTRIBUTE_VGA_MEMORY | \
+ EFI_PCI_ATTRIBUTE_VGA_IO_16 | EFI_PCI_ATTRIBUTE_VGA_PALETTE_IO_16;
+ PrivateData->Attributes = PrivateData->Supports;
+
+ Protocol->ParentHandle = HostBridgeHandle;
+
+ Protocol->PollMem = RootBridgeIoPollMem;
+ Protocol->PollIo = RootBridgeIoPollIo;
+
+ Protocol->Mem.Read = RootBridgeIoMemRead;
+ Protocol->Mem.Write = RootBridgeIoMemWrite;
+
+ Protocol->Io.Read = RootBridgeIoIoRead;
+ Protocol->Io.Write = RootBridgeIoIoWrite;
+
+ Protocol->CopyMem = RootBridgeIoCopyMem;
+
+ Protocol->Pci.Read = RootBridgeIoPciRead;
+ Protocol->Pci.Write = RootBridgeIoPciWrite;
+
+ Protocol->Map = RootBridgeIoMap;
+ Protocol->Unmap = RootBridgeIoUnmap;
+
+ Protocol->AllocateBuffer = RootBridgeIoAllocateBuffer;
+ Protocol->FreeBuffer = RootBridgeIoFreeBuffer;
+
+ Protocol->Flush = RootBridgeIoFlush;
+
+ Protocol->GetAttributes = RootBridgeIoGetAttributes;
+ Protocol->SetAttributes = RootBridgeIoSetAttributes;
+
+ Protocol->Configuration = RootBridgeIoConfiguration;
+
+ Protocol->SegmentNumber = HostNo;
+
+ Status = gBS->LocateProtocol (&gEfiMetronomeArchProtocolGuid, NULL, (VOID **)&mMetronome);
+ ASSERT_EFI_ERROR (Status);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ This function provides a standard way to poll a PCI memory location. A PCI memory read
+ operation is performed at the PCI memory address specified by Address for the width specified
+ by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
+ read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
+ Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // No matter what, always do a single poll.
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks) {
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ Status = This->Mem.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+
+ return EFI_TIMEOUT;
+}
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
+ performed at the PCI I/O address specified by Address for the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
+ repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
+ to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ )
+{
+ EFI_STATUS Status;
+ UINT64 NumberOfTicks;
+ UINT32 Remainder;
+
+ if (Result == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // No matter what, always do a single poll.
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ if (Delay == 0) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks = DivU64x32Remainder (Delay, (UINT32) mMetronome->TickPeriod, &Remainder);
+ if (Remainder != 0) {
+ NumberOfTicks += 1;
+ }
+ NumberOfTicks += 1;
+
+ while (NumberOfTicks) {
+ mMetronome->WaitForTick (mMetronome, 1);
+
+ Status = This->Io.Read (This, Width, Address, 1, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if ((*Result & Mask) == Value) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfTicks -= 1;
+ }
+
+ return EFI_TIMEOUT;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoMemRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoMemRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return RootBridgeIoIoRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ if (Buffer == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Width >= EfiPciWidthMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ return RootBridgeIoIoRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
+ space to another region of PCI root bridge memory space. This is especially useful for video scroll
+ operation on a memory mapped video buffer.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] DestAddress The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Direction;
+ UINTN Stride;
+ UINTN Index;
+ UINT64 Result;
+
+ if (Width > EfiPciWidthUint64) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (DestAddress == SrcAddress) {
+ return EFI_SUCCESS;
+ }
+
+ Stride = (UINTN)(1 << Width);
+
+ Direction = TRUE;
+ if ((DestAddress > SrcAddress) && (DestAddress < (SrcAddress + Count * Stride))) {
+ Direction = FALSE;
+ SrcAddress = SrcAddress + (Count-1) * Stride;
+ DestAddress = DestAddress + (Count-1) * Stride;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ Status = RootBridgeIoMemRead (
+ This,
+ Width,
+ SrcAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = RootBridgeIoMemWrite (
+ This,
+ Width,
+ DestAddress,
+ 1,
+ &Result
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (Direction) {
+ SrcAddress += Stride;
+ DestAddress += Stride;
+ } else {
+ SrcAddress -= Stride;
+ DestAddress -= Stride;
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ )
+{
+ return RootBridgeIoPciRW (This, FALSE, Width, Address, Count, Buffer);
+}
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ )
+{
+ return RootBridgeIoPciRW (This, TRUE, Width, Address, Count, Buffer);
+}
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ The Map() function provides the PCI controller specific addresses needed to access system
+ memory. This function is used to map system memory for PCI bus master DMA accesses.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+ MAP_INFO *MapInfo;
+
+ if (HostAddress == NULL || NumberOfBytes == NULL || DeviceAddress == NULL || Mapping == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Initialize the return values to their defaults
+ //
+ *Mapping = NULL;
+
+ //
+ // Make sure that Operation is valid
+ //
+ if ((UINT32)Operation >= EfiPciOperationMaximum) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((*NumberOfBytes) > PcdGet64 (PcdPciMemOneTransaction)) {
+ DEBUG((DEBUG_INFO, "Cannot map more than 0x%x at one transaction\n",
+ PcdGet64 (PcdPciMemOneTransaction)));
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // If any part of the DMA transfer being mapped is above 4GB, then
+ // map the DMA transfer to a buffer below 4GB
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress;
+ if ((PhysicalAddress + *NumberOfBytes) > 0x100000000ULL) {
+
+ //
+ // Common Buffer operations can not be remapped. If the common buffer
+ // if above 4GB, then it is not possible to generate a mapping, so return
+ // an error.
+ //
+ if (Operation == EfiPciOperationBusMasterCommonBuffer || Operation == EfiPciOperationBusMasterCommonBuffer64) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Allocate a MAP_INFO structure to remember the mapping when Unmap() is
+ // called later.
+ //
+ Status = gBS->AllocatePool (
+ EfiBootServicesData,
+ sizeof (MAP_INFO),
+ (VOID **)&MapInfo
+ );
+ if (EFI_ERROR (Status)) {
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ //
+ // Return a pointer to the MAP_INFO structure in Mapping
+ //
+ *Mapping = MapInfo;
+
+ //
+ // Initialize the MAP_INFO structure
+ //
+ MapInfo->Operation = Operation;
+ MapInfo->NumberOfBytes = *NumberOfBytes;
+ MapInfo->NumberOfPages = EFI_SIZE_TO_PAGES (*NumberOfBytes);
+ MapInfo->HostAddress = PhysicalAddress;
+ MapInfo->MappedHostAddress = GetPciAddressSpaceMask ();
+
+ //
+ // Allocate a buffer below 4GB to map the transfer to.
+ //
+ Status = gBS->AllocatePages (
+ AllocateMaxAddress,
+ EfiBootServicesData,
+ MapInfo->NumberOfPages,
+ &MapInfo->MappedHostAddress
+ );
+ if (EFI_ERROR (Status)) {
+ gBS->FreePool (MapInfo);
+ *NumberOfBytes = 0;
+ return Status;
+ }
+
+ //
+ // If this is a read operation from the Bus Master's point of view,
+ // then copy the contents of the real buffer into the mapped buffer
+ // so the Bus Master can read the contents of the real buffer.
+ //
+ if (Operation == EfiPciOperationBusMasterRead || Operation == EfiPciOperationBusMasterRead64) {
+ CopyMem (
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ (VOID *)(UINTN)MapInfo->HostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+
+ //
+ // The DeviceAddress is the address of the maped buffer below 4GB
+ //
+ *DeviceAddress = MapInfo->MappedHostAddress;
+ } else {
+ //
+ // The transfer is below 4GB, so the DeviceAddress is simply the HostAddress
+ //
+ *DeviceAddress = PhysicalAddress;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ The Unmap() function completes the Map() operation and releases any corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
+ Any resources used for the mapping are freed.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ )
+{
+ MAP_INFO *MapInfo;
+
+ //
+ // See if the Map() operation associated with this Unmap() required a mapping buffer.
+ // If a mapping buffer was not required, then this function simply returns EFI_SUCCESS.
+ //
+ if (Mapping != NULL) {
+ //
+ // Get the MAP_INFO structure from Mapping
+ //
+ MapInfo = (MAP_INFO *)Mapping;
+
+ //
+ // If this is a write operation from the Bus Master's point of view,
+ // then copy the contents of the mapped buffer into the real buffer
+ // so the processor can read the contents of the real buffer.
+ //
+ if (MapInfo->Operation == EfiPciOperationBusMasterWrite || MapInfo->Operation == EfiPciOperationBusMasterWrite64) {
+ CopyMem (
+ (VOID *)(UINTN)MapInfo->HostAddress,
+ (VOID *)(UINTN)MapInfo->MappedHostAddress,
+ MapInfo->NumberOfBytes
+ );
+ }
+
+ //
+ // Free the mapped buffer and the MAP_INFO structure.
+ //
+ gBS->FreePages (MapInfo->MappedHostAddress, MapInfo->NumberOfPages);
+ gBS->FreePool (Mapping);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CAC HED,and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PhysicalAddress;
+
+ //
+ // Validate Attributes
+ //
+ if ((Attributes & EFI_PCI_ATTRIBUTE_INVALID_FOR_ALLOCATE_BUFFER) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+
+ //
+ // Check for invalid inputs
+ //
+ if (HostAddress == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // The only valid memory types are EfiBootServicesData and EfiRuntimeServicesData
+ //
+ if (MemoryType != EfiBootServicesData && MemoryType != EfiRuntimeServicesData) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Limit allocations to memory below 4GB
+ //
+ PhysicalAddress = (EFI_PHYSICAL_ADDRESS)(GetPciAddressSpaceMask ());
+
+ Status = gBS->AllocatePages (AllocateMaxAddress, MemoryType, Pages, &PhysicalAddress);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ *HostAddress = (VOID *)(UINTN)PhysicalAddress;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ )
+{
+
+ return gBS->FreePages ((EFI_PHYSICAL_ADDRESS) (UINTN) HostAddress, Pages);
+}
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
+ memory. Posted write transactions are generated by PCI bus masters when they perform write
+ transactions to target addresses in system memory.
+ This function does not flush posted write transactions from any PCI bridges. A PCI controller
+ specific action must be taken to guarantee that the posted write transactions have been flushed from
+ the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
+ a PCI read transaction from the PCI controller prior to calling Flush().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ )
+{
+ //
+ // not supported yet
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
+ and the mask of attributes that the PCI root bridge is currently using
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (Attributes == NULL && Supported == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // Set the return value for Supported and Attributes
+ //
+ if (Supported != NULL) {
+ *Supported = PrivateData->Supports;
+ }
+
+ if (Attributes != NULL) {
+ *Attributes = PrivateData->Attributes;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for the PCI root
+ bridge on the resource range specified by ResourceBase and ResourceLength. Since the
+ granularity of setting these attributes may vary from resource type to resource type, and from
+ platform to platform, the actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a larger resource range
+ than the caller requested. The actual range is returned in ResourceBase and
+ ResourceLength. The caller is responsible for verifying that the actual range for which the
+ attributes were set is acceptable.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ )
+{
+ PCI_ROOT_BRIDGE_INSTANCE *PrivateData;
+
+ PrivateData = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ if (Attributes != 0) {
+ if ((Attributes & (~(PrivateData->Supports))) != 0) {
+ return EFI_UNSUPPORTED;
+ }
+ }
+
+ //
+ // This is a generic driver for a PC-AT class system. It does not have any
+ // chipset specific knowlegde, so none of the attributes can be set or
+ // cleared. Any attempt to set attribute that are already set will succeed,
+ // and any attempt to set an attribute that is not supported will fail.
+ //
+ if (Attributes & (~PrivateData->Attributes)) {
+ return EFI_UNSUPPORTED;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ There are only two resource descriptor types from the ACPI Specification that may be used to
+ describe the current resources allocated to a PCI root bridge. These are the QWORD Address
+ Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
+ QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
+ or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
+ Address Space Descriptors followed by an End Tag.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+)
+{
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
+ UINTN Index;
+
+ RootBridge = DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS (This);
+
+ for (Index = 0; Index < ResTypeMax; Index++) {
+ if (RootBridge->ResAlloc[Index].Length != 0) {
+ Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->ResAlloc[Index].Base;
+ Configuration.SpaceDesp[Index].AddrRangeMax = RootBridge->ResAlloc[Index].Base + RootBridge->ResAlloc[Index].Length - 1;
+ Configuration.SpaceDesp[Index].AddrLen = RootBridge->ResAlloc[Index].Length;
+ }
+ }
+
+ // Set up Configuration for the bus
+ Configuration.SpaceDesp[Index].AddrRangeMin = RootBridge->BusStart;
+ Configuration.SpaceDesp[Index].AddrLen = RootBridge->BusLength;
+
+ *Resources = &Configuration;
+ return EFI_SUCCESS;
+}
diff --git a/Platform/NXP/Include/PciHostBridge.h b/Platform/NXP/Include/PciHostBridge.h
new file mode 100644
index 0000000..cfca971
--- /dev/null
+++ b/Platform/NXP/Include/PciHostBridge.h
@@ -0,0 +1,466 @@
+/** PciHostBridge.h
+ The Header file of the Pci Host Bridge Driver
+
+ Some part of code is inspired from EDK II, File:
+ PcAtChipsetPkg/PciHostBridgeDxe/PciHostBridge.h
+
+ Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved. <BR>
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI_HOST_BRIDGE_H_
+#define _PCI_HOST_BRIDGE_H_
+
+#include <PiDxe.h>
+
+#include <IndustryStandard/Pci.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/DxeServicesTableLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Protocol/Metronome.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <SerDes.h>
+
+#include "PciCntrlLib.h"
+
+#define MAX_PCI_DEVICE_NUMBER 31
+#define MAX_PCI_FUNCTION_NUMBER 7
+#define MAX_PCI_REG_ADDRESS (SIZE_4KB - 1)
+
+#define LS_PCIE_CFG0_PHYS_OFF 0x00000000
+#define LS_PCIE_CFG0_SIZE 0x00001000 /* 4k */
+#define LS_PCIE_CFG1_PHYS_OFF 0x00001000
+#define LS_PCIE_CFG1_SIZE 0x00001000 /* 4k */
+
+#define LS_PCIE_IO_BUS 0x00000000
+#define LS_PCIE_IO_PHYS_OFF 0x00010000
+#define LS_PCIE_IO_SIZE 0x00010000 /* 64k */
+
+#define LS_PCIE_MEM_BUS 0x40000000
+#define LS_PCIE_MEM_PHYS_OFF 0x40000000
+#define LS_PCIE_MEM_SIZE 0x40000000 /* 1 GB */
+
+#define PCI_MEM64_SIZE FixedPcdGet64 (PcdPciMmio64Size)
+
+#define NUM_PCIE_CONTROLLER FixedPcdGet32 (PcdNumPciController)
+
+#define PCI_MMIO64_BASE_DIFFERENCE 0x800000000
+
+typedef enum {
+ IoOperation,
+ MemOperation,
+ PciOperation
+} OPERATION_TYPE;
+
+#define PCI_HOST_BRIDGE_SIGNATURE SIGNATURE_32('p', 'c', 'i', 'h')
+typedef struct PCI_HOST_BRIDGE_INSTANCE_ST {
+ UINTN Signature;
+ EFI_HANDLE HostBridgeHandle;
+ EFI_HANDLE ImageHandle;
+ UINTN RootBridgeNumber[4];
+ PCI_ROOT_BRIDGE_INSTANCE *RootBridge;
+ LIST_ENTRY Head;
+ BOOLEAN ResourceSubmited;
+ BOOLEAN CanRestarted;
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL ResAlloc;
+} PCI_HOST_BRIDGE_INSTANCE;
+
+#define INSTANCE_FROM_RESOURCE_ALLOCATION_THIS(a) \
+ CR(a, PCI_HOST_BRIDGE_INSTANCE, ResAlloc, PCI_HOST_BRIDGE_SIGNATURE)
+
+//
+// HostBridge Resource Allocation interface
+//
+/**
+ These are the notifications from the PCI bus driver that it is about to enter a certain
+ phase of the PCI enumeration process.
+
+ This member function can be used to notify the host bridge driver to perform specific actions,
+ including any chipset-specific initialization, so that the chipset is ready to enter the next phase.
+ Eight notification points are defined at this time. See belows:
+ EfiPciHostBridgeBeginEnumeration Resets the host bridge PCI apertures and internal data
+ structures. The PCI enumerator should issue this notification
+ before starting a fresh enumeration process. Enumeration cannot
+ be restarted after sending any other notification such as
+ EfiPciHostBridgeBeginBusAllocation.
+ EfiPciHostBridgeBeginBusAllocation The bus allocation phase is about to begin. No specific action is
+ required here. This notification can be used to perform any
+ chipset-specific programming.
+ EfiPciHostBridgeEndBusAllocation The bus allocation and bus programming phase is complete. No
+ specific action is required here. This notification can be used to
+ perform any chipset-specific programming.
+ EfiPciHostBridgeBeginResourceAllocation
+ The resource allocation phase is about to begin. No specific
+ action is required here. This notification can be used to perform
+ any chipset-specific programming.
+ EfiPciHostBridgeAllocateResources Allocates resources per previously submitted requests for all the PCI
+ root bridges. These resource settings are returned on the next call to
+ GetProposedResources(). Before calling NotifyPhase() with a Phase of
+ EfiPciHostBridgeAllocateResource, the PCI bus enumerator is responsible
+ for gathering I/O and memory requests for
+ all the PCI root bridges and submitting these requests using
+ SubmitResources(). This function pads the resource amount
+ to suit the root bridge hardware, takes care of dependencies between
+ the PCI root bridges, and calls the Global Coherency Domain (GCD)
+ with the allocation request. In the case of padding, the allocated range
+ could be bigger than what was requested.
+ EfiPciHostBridgeSetResources Programs the host bridge hardware to decode previously allocated
+ resources (proposed resources) for all the PCI root bridges. After the
+ hardware is programmed, reassigning resources will not be supported.
+ The bus settings are not affected.
+ EfiPciHostBridgeFreeResources Deallocates resources that were previously allocated for all the PCI
+ root bridges and resets the I/O and memory apertures to their initial
+ state. The bus settings are not affected. If the request to allocate
+ resources fails, the PCI enumerator can use this notification to
+ deallocate previous resources, adjust the requests, and retry
+ allocation.
+ EfiPciHostBridgeEndResourceAllocation The resource allocation phase is completed. No specific action is
+ required here. This notification can be used to perform any chipsetspecific
+ programming.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] Phase The phase during enumeration
+
+ @retval EFI_NOT_READY This phase cannot be entered at this time. For example, this error
+ is valid for a Phase of EfiPciHostBridgeAllocateResources if
+ SubmitResources() has not been called for one or more
+ PCI root bridges before this call
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. This error is valid
+ for a Phase of EfiPciHostBridgeSetResources.
+ @retval EFI_INVALID_PARAMETER Invalid phase parameter
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+ This error is valid for a Phase of EfiPciHostBridgeAllocateResources if the
+ previously submitted resource requests cannot be fulfilled or
+ were only partially fulfilled.
+ @retval EFI_SUCCESS The notification was accepted without any errors.
+
+**/
+EFI_STATUS
+EFIAPI
+PciNotifyPhase(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+/**
+ Return the device handle of the next PCI root bridge that is associated with this Host Bridge.
+
+ This function is called multiple times to retrieve the device handles of all the PCI root bridges that
+ are associated with this PCI host bridge. Each PCI host bridge is associated with one or more PCI
+ root bridges. On each call, the handle that was returned by the previous call is passed into the
+ interface, and on output the interface returns the device handle of the next PCI root bridge. The
+ caller can use the handle to obtain the instance of the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+ for that root bridge. When there are no more PCI root bridges to report, the interface returns
+ EFI_NOT_FOUND. A PCI enumerator must enumerate the PCI root bridges in the order that they
+ are returned by this function.
+ For D945 implementation, there is only one root bridge in PCI host bridge.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in, out] RootBridgeHandle Returns the device handle of the next PCI root bridge.
+
+ @retval EFI_SUCCESS If parameter RootBridgeHandle = NULL, then return the first Rootbridge handle of the
+ specific Host bridge and return EFI_SUCCESS.
+ @retval EFI_NOT_FOUND Can not find the any more root bridge in specific host bridge.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not an EFI_HANDLE that was
+ returned on a previous call to GetNextRootBridge().
+**/
+EFI_STATUS
+EFIAPI
+PciGetNextRootBridge(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN OUT EFI_HANDLE *RootBridgeHandle
+ );
+
+/**
+ Returns the allocation attributes of a PCI root bridge.
+
+ The function returns the allocation attributes of a specific PCI root bridge. The attributes can vary
+ from one PCI root bridge to another. These attributes are different from the decode-related
+ attributes that are returned by the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.GetAttributes() member function. The
+ RootBridgeHandle parameter is used to specify the instance of the PCI root bridge. The device
+ handles of all the root bridges that are associated with this host bridge must be obtained by calling
+ GetNextRootBridge(). The attributes are static in the sense that they do not change during or
+ after the enumeration process. The hardware may provide mechanisms to change the attributes on
+ the fly, but such changes must be completed before EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL is
+ installed. The permitted values of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ATTRIBUTES are defined in
+ "Related Definitions" below. The caller uses these attributes to combine multiple resource requests.
+ For example, if the flag EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM is set, the PCI bus enumerator needs to
+ include requests for the prefetchable memory in the nonprefetchable memory pool and not request any
+ prefetchable memory.
+ Attribute Description
+ ------------------------------------ ----------------------------------------------------------------------
+ EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM If this bit is set, then the PCI root bridge does not support separate
+ windows for nonprefetchable and prefetchable memory. A PCI bus
+ driver needs to include requests for prefetchable memory in the
+ nonprefetchable memory pool.
+
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE If this bit is set, then the PCI root bridge supports 64-bit memory
+ windows. If this bit is not set, the PCI bus driver needs to include
+ requests for a 64-bit memory address in the corresponding 32-bit
+ memory pool.
+
+ @param[in] This The instance pointer of EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ @param[in] RootBridgeHandle The device handle of the PCI root bridge in which the caller is interested. Type
+ EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Attributes The pointer to attribte of root bridge, it is output parameter
+
+ @retval EFI_INVALID_PARAMETER Attribute pointer is NULL
+ @retval EFI_INVALID_PARAMETER RootBridgehandle is invalid.
+ @retval EFI_SUCCESS Success to get attribute of interested root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PciGetAllocAttributes(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets up the specified PCI root bridge for the bus enumeration process.
+
+ This member function sets up the root bridge for bus enumeration and returns the PCI bus range
+ over which the search should be performed in ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI Root Bridge to be set up.
+ @param[out] Configuration Pointer to the pointer to the PCI bus resource descriptor.
+
+ @retval EFI_INVALID_PARAMETER Invalid Root bridge's handle
+ @retval EFI_OUT_OF_RESOURCES Fail to allocate ACPI resource descriptor tag.
+ @retval EFI_SUCCESS Sucess to allocate ACPI resource descriptor.
+
+**/
+EFI_STATUS
+EFIAPI
+PciStartBusEnumeration(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+/**
+ Programs the PCI root bridge hardware so that it decodes the specified PCI bus range.
+
+ This member function programs the specified PCI root bridge to decode the bus range that is
+ specified by the input parameter Configuration.
+ The bus range information is specified in terms of the ACPI 2.0 resource descriptor format.
+
+ @param[in] This The EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_ PROTOCOL instance
+ @param[in] RootBridgeHandle The PCI Root Bridge whose bus range is to be programmed
+ @param[in] Configuration The pointer to the PCI bus resource descriptor
+
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration does not include a valid ACPI 2.0 bus resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes valid ACPI 2.0 resource descriptors other than
+ bus descriptors.
+ @retval EFI_INVALID_PARAMETER Configuration contains one or more invalid ACPI resource descriptors.
+ @retval EFI_INVALID_PARAMETER "Address Range Minimum" is invalid for this root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this root bridge.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_SUCCESS The bus range for the PCI root bridge was programmed.
+
+**/
+EFI_STATUS
+EFIAPI
+PciSetBusNumbers(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+/**
+ Submits the I/O and memory resource requirements for the specified PCI root bridge.
+
+ This function is used to submit all the I/O and memory resources that are required by the specified
+ PCI root bridge. The input parameter Configuration is used to specify the following:
+ - The various types of resources that are required
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge whose I/O and memory resource requirements are being submitted.
+ @param[in] Configuration The pointer to the PCI I/O and PCI memory resource descriptor.
+
+ @retval EFI_SUCCESS The I/O and memory resource requests for a PCI root bridge were accepted.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Configuration is NULL.
+ @retval EFI_INVALID_PARAMETER Configuration does not point to a valid ACPI 2.0 resource descriptor.
+ @retval EFI_INVALID_PARAMETER Configuration includes requests for one or more resource types that are
+ not supported by this PCI root bridge. This error will happen if the caller
+ did not combine resources according to Attributes that were returned by
+ GetAllocAttributes().
+ @retval EFI_INVALID_PARAMETER Address Range Maximum" is invalid.
+ @retval EFI_INVALID_PARAMETER "Address Range Length" is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER "Address Space Granularity" is invalid for this PCI root bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PciSubmitResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN VOID *Configuration
+ );
+
+/**
+ Returns the proposed resource settings for the specified PCI root bridge.
+
+ This member function returns the proposed resource settings for the specified PCI root bridge. The
+ proposed resource settings are prepared when NotifyPhase() is called with a Phase of
+ EfiPciHostBridgeAllocateResources. The output parameter Configuration
+ specifies the following:
+ - The various types of resources, excluding bus resources, that are allocated
+ - The associated lengths in terms of ACPI 2.0 resource descriptor format
+
+ @param[in] This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param[in] RootBridgeHandle The PCI root bridge handle. Type EFI_HANDLE is defined in InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param[out] Configuration The pointer to the pointer to the PCI I/O and memory resource descriptor.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+PciGetProposedResources(
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ OUT VOID **Configuration
+ );
+
+/**
+ Provides the hooks from the PCI bus driver to every PCI controller (device/function) at various
+ stages of the PCI enumeration process that allow the host bridge driver to preinitialize individual
+ PCI controllers before enumeration.
+
+ This function is called during the PCI enumeration process. No specific action is expected from this
+ member function. It allows the host bridge driver to preinitialize individual PCI controllers before
+ enumeration.
+
+ @param This Pointer to the EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL instance.
+ @param RootBridgeHandle The associated PCI root bridge handle. Type EFI_HANDLE is defined in
+ InstallProtocolInterface() in the UEFI 2.0 Specification.
+ @param PciAddress The address of the PCI device on the PCI bus. This address can be passed to the
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL member functions to access the PCI
+ configuration space of the device. See Table 12-1 in the UEFI 2.0 Specification for
+ the definition of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS.
+ @param Phase The phase of the PCI device enumeration.
+
+ @retval EFI_SUCCESS The requested parameters were returned.
+ @retval EFI_INVALID_PARAMETER RootBridgeHandle is not a valid root bridge handle.
+ @retval EFI_INVALID_PARAMETER Phase is not a valid phase that is defined in
+ EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE.
+ @retval EFI_DEVICE_ERROR Programming failed due to a hardware error. The PCI enumerator should
+ not enumerate this device, including its child devices if it is a PCI-to-PCI
+ bridge.
+
+**/
+EFI_STATUS
+EFIAPI
+PciPreprocessController (
+ IN EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL *This,
+ IN EFI_HANDLE RootBridgeHandle,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_PCI_ADDRESS PciAddress,
+ IN EFI_PCI_CONTROLLER_RESOURCE_ALLOCATION_PHASE Phase
+ );
+
+
+//
+// Define resource status constant
+//
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+
+//
+// Driver Instance Data Prototypes
+//
+
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation;
+ UINTN NumberOfBytes;
+ UINTN NumberOfPages;
+ EFI_PHYSICAL_ADDRESS HostAddress;
+ EFI_PHYSICAL_ADDRESS MappedHostAddress;
+} MAP_INFO;
+
+typedef enum {
+ ResNone = 0,
+ ResSubmitted,
+ ResRequested,
+ ResAllocated,
+ ResStatusMax
+} RES_STATUS;
+
+typedef struct {
+ PCI_RESOURCE_TYPE Type;
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+ RES_STATUS Status;
+} PCI_RES_NODE;
+
+#define PCI_ROOT_BRIDGE_SIGNATURE SIGNATURE_32('P', 'C', 'I', '3')
+
+//
+// Driver Instance Data Macros
+//
+#define DRIVER_INSTANCE_FROM_PCI_ROOT_BRIDGE_IO_THIS(a) \
+ CR(a, PCI_ROOT_BRIDGE_INSTANCE, Io, PCI_ROOT_BRIDGE_SIGNATURE)
+
+
+#define DRIVER_INSTANCE_FROM_LIST_ENTRY(a) \
+ CR(a, PCI_ROOT_BRIDGE_INSTANCE, Link, PCI_ROOT_BRIDGE_SIGNATURE)
+
+/**
+ Initialize and create Pci Root Bridges for Board
+
+ @param PrvateData Driver instance of this Root Bridge IO protocol
+ @param Protocol Point to protocol instance
+ @param Info Point to Info field of this driver instance
+ @param HostBridgeHandle Handle of host bridge
+ @param Attri Attribute of host bridge
+ @param HostNo HostNo for this Host Bridge
+ @param Busno Bus Number for the Host Bridge
+
+ @retval EFI_SUCCESS Success to initialize the Pci Root Bridge.
+
+**/
+
+EFI_STATUS
+PciRbInitialize (
+ IN PCI_ROOT_BRIDGE_INSTANCE *PrivateData,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Protocol,
+ IN LsPcieInfo *Info,
+ IN EFI_HANDLE HostBridgeHandle,
+ IN UINT64 Attri,
+ IN INTN HostNo,
+ IN INTN Busno,
+ IN UINT64 *PciBaseAddr
+);
+
+/**
+ Function to return PCI addess space mask
+**/
+UINT64
+GetPciAddressSpaceMask (
+ IN VOID
+ );
+
+#endif
diff --git a/Platform/NXP/Include/PciRootBridge.h b/Platform/NXP/Include/PciRootBridge.h
new file mode 100644
index 0000000..cd22e48
--- /dev/null
+++ b/Platform/NXP/Include/PciRootBridge.h
@@ -0,0 +1,674 @@
+/** PciRootBridge.h
+ The Header file of the Pci Root Bridge driver
+
+ Copyright 2017 NXP
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _PCI_LS_H_
+#define _PCI_LS_H_
+
+#include <Library/IoLib.h>
+
+#define MAX_PCI_REGIONS 7
+
+typedef UINT64 PciAddrT;
+typedef UINT64 PciSizeT;
+typedef UINT64 PhysAddrT;
+typedef UINT64 PhysSizeT;
+typedef INTN PciDevT;
+
+//
+// Protocol Member Function Prototypes
+//
+
+/**
+ Polls an address in memory mapped I/O space until an exit condition is met, or
+ a timeout occurs.
+
+ This function provides a standard way to poll a PCI memory location. A PCI memory read
+ operation is performed at the PCI memory address specified by Address for the width specified
+ by Width. The result of this PCI memory read operation is stored in Result. This PCI memory
+ read operation is repeated until either a timeout of Delay 100 ns units has expired, or (Result &
+ Mask) is equal to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The base address of the memory operations. The caller is
+ responsible for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the memory address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+/**
+ Reads from the I/O space of a PCI Root Bridge. Returns when either the polling exit criteria is
+ satisfied or after a defined duration.
+
+ This function provides a standard way to poll a PCI I/O location. A PCI I/O read operation is
+ performed at the PCI I/O address specified by Address for the width specified by Width.
+ The result of this PCI I/O read operation is stored in Result. This PCI I/O read operation is
+ repeated until either a timeout of Delay 100 ns units has expired, or (Result & Mask) is equal
+ to Value.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the I/O operations.
+ @param[in] Address The base address of the I/O operations. The caller is responsible
+ for aligning Address if required.
+ @param[in] Mask Mask used for the polling criteria. Bytes above Width in Mask
+ are ignored. The bits in the bytes below Width which are zero in
+ Mask are ignored when polling the I/O address.
+ @param[in] Value The comparison value used for the polling exit criteria.
+ @param[in] Delay The number of 100 ns units to poll. Note that timer available may
+ be of poorer granularity.
+ @param[out] Result Pointer to the last value read from the memory location.
+
+ @retval EFI_SUCCESS The last data returned from the access matched the poll exit criteria.
+ @retval EFI_INVALID_PARAMETER Width is invalid.
+ @retval EFI_INVALID_PARAMETER Result is NULL.
+ @retval EFI_TIMEOUT Delay expired before a match occurred.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPollIo (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINT64 Mask,
+ IN UINT64 Value,
+ IN UINT64 Delay,
+ OUT UINT64 *Result
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge memory space.
+
+ The Mem.Read(), and Mem.Write() functions enable a driver to access PCI controller
+ registers in the PCI root bridge memory space.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI Root Bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operation.
+ @param[in] Address The base address of the memory operation. The caller is
+ responsible for aligning the Address if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[out] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ OUT VOID *UserBuffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in the PCI root bridge I/O space.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] UserAddress The base address of the I/O operation. The caller is responsible for
+ aligning the Address if required.
+ @param[in] Count The number of I/O operations to perform. Bytes moved is Width
+ size * Count, starting at Address.
+ @param[in] UserBuffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoIoWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 UserAddress,
+ IN UINTN Count,
+ IN VOID *UserBuffer
+ );
+
+/**
+ Enables a PCI driver to copy one region of PCI root bridge memory space to another region of PCI
+ root bridge memory space.
+
+ The CopyMem() function enables a PCI driver to copy one region of PCI root bridge memory
+ space to another region of PCI root bridge memory space. This is especially useful for video scroll
+ operation on a memory mapped video buffer.
+ The memory operations are carried out exactly as requested. The caller is responsible for satisfying
+ any alignment and memory width restrictions that a PCI root bridge on a platform might require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL instance.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] DestAddress The destination address of the memory operation. The caller is
+ responsible for aligning the DestAddress if required.
+ @param[in] SrcAddress The source address of the memory operation. The caller is
+ responsible for aligning the SrcAddress if required.
+ @param[in] Count The number of memory operations to perform. Bytes moved is
+ Width size * Count, starting at DestAddress and SrcAddress.
+
+ @retval EFI_SUCCESS The data was copied from one memory region to another memory region.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoCopyMem (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 DestAddress,
+ IN UINT64 SrcAddress,
+ IN UINTN Count
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[out] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ OUT VOID *Buffer
+ );
+
+/**
+ Enables a PCI driver to access PCI controller registers in a PCI root bridge's configuration space.
+
+ The Pci.Read() and Pci.Write() functions enable a driver to access PCI configuration
+ registers for a PCI controller.
+ The PCI Configuration operations are carried out exactly as requested. The caller is responsible for
+ any alignment and PCI configuration width issues that a PCI Root Bridge on a platform might
+ require.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Width Signifies the width of the memory operations.
+ @param[in] Address The address within the PCI configuration space for the PCI controller.
+ @param[in] Count The number of PCI configuration operations to perform. Bytes
+ moved is Width size * Count, starting at Address.
+ @param[in] Buffer For read operations, the destination buffer to store the results. For
+ write operations, the source buffer to write data from.
+
+ @retval EFI_SUCCESS The data was read from or written to the PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Width is invalid for this PCI root bridge.
+ @retval EFI_INVALID_PARAMETER Buffer is NULL.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoPciWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN VOID *Buffer
+ );
+
+/**
+ Provides the PCI controller-specific addresses required to access system memory from a
+ DMA bus master.
+
+ The Map() function provides the PCI controller specific addresses needed to access system
+ memory. This function is used to map system memory for PCI bus master DMA accesses.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Operation Indicates if the bus master is going to read or write to system memory.
+ @param[in] HostAddress The system memory address to map to the PCI controller.
+ @param[in, out] NumberOfBytes On input the number of bytes to map. On output the number of bytes that were mapped.
+ @param[out] DeviceAddress The resulting map address for the bus master PCI controller to use
+ to access the system memory's HostAddress.
+ @param[out] Mapping The value to pass to Unmap() when the bus master DMA operation is complete.
+
+ @retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
+ @retval EFI_INVALID_PARAMETER Operation is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_INVALID_PARAMETER NumberOfBytes is NULL.
+ @retval EFI_INVALID_PARAMETER DeviceAddress is NULL.
+ @retval EFI_INVALID_PARAMETER Mapping is NULL.
+ @retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
+ @retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
+ @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoMap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_OPERATION Operation,
+ IN VOID *HostAddress,
+ IN OUT UINTN *NumberOfBytes,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ );
+
+/**
+ Completes the Map() operation and releases any corresponding resources.
+
+ The Unmap() function completes the Map() operation and releases any corresponding resources.
+ If the operation was an EfiPciOperationBusMasterWrite or
+ EfiPciOperationBusMasterWrite64, the data is committed to the target system memory.
+ Any resources used for the mapping are freed.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Mapping The mapping value returned from Map().
+
+ @retval EFI_SUCCESS The range was unmapped.
+ @retval EFI_INVALID_PARAMETER Mapping is not a value that was returned by Map().
+ @retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoUnmap (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN VOID *Mapping
+ );
+
+/**
+ Allocates pages that are suitable for an EfiPciOperationBusMasterCommonBuffer or
+ EfiPciOperationBusMasterCommonBuffer64 mapping.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Type This parameter is not used and must be ignored.
+ @param MemoryType The type of memory to allocate, EfiBootServicesData or EfiRuntimeServicesData.
+ @param Pages The number of pages to allocate.
+ @param HostAddress A pointer to store the base system memory address of the allocated range.
+ @param Attributes The requested bit mask of attributes for the allocated range. Only
+ the attributes EFI_PCI_ATTRIBUTE_MEMORY_WRITE_COMBINE, EFI_PCI_ATTRIBUTE_MEMORY_CACHED,
+ and EFI_PCI_ATTRIBUTE_DUAL_ADDRESS_CYCLE may be used with this function.
+
+ @retval EFI_SUCCESS The requested memory pages were allocated.
+ @retval EFI_INVALID_PARAMETER MemoryType is invalid.
+ @retval EFI_INVALID_PARAMETER HostAddress is NULL.
+ @retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and DUAL_ADDRESS_CYCLE.
+ @retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoAllocateBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN EFI_ALLOCATE_TYPE Type,
+ IN EFI_MEMORY_TYPE MemoryType,
+ IN UINTN Pages,
+ OUT VOID **HostAddress,
+ IN UINT64 Attributes
+ );
+
+/**
+ Frees memory that was allocated with AllocateBuffer().
+
+ The FreeBuffer() function frees memory that was allocated with AllocateBuffer().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Pages The number of pages to free.
+ @param HostAddress The base system memory address of the allocated range.
+
+ @retval EFI_SUCCESS The requested memory pages were freed.
+ @retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
+ was not allocated with AllocateBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFreeBuffer (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINTN Pages,
+ OUT VOID *HostAddress
+ );
+
+/**
+ Flushes all PCI posted write transactions from a PCI host bridge to system memory.
+
+ The Flush() function flushes any PCI posted write transactions from a PCI host bridge to system
+ memory. Posted write transactions are generated by PCI bus masters when they perform write
+ transactions to target addresses in system memory.
+ This function does not flush posted write transactions from any PCI bridges. A PCI controller
+ specific action must be taken to guarantee that the posted write transactions have been flushed from
+ the PCI controller and from all the PCI bridges into the PCI host bridge. This is typically done with
+ a PCI read transaction from the PCI controller prior to calling Flush().
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+
+ @retval EFI_SUCCESS The PCI posted write transactions were flushed from the PCI host
+ bridge to system memory.
+ @retval EFI_DEVICE_ERROR The PCI posted write transactions were not flushed from the PCI
+ host bridge due to a hardware error.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoFlush (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This
+ );
+
+/**
+ Gets the attributes that a PCI root bridge supports setting with SetAttributes(), and the
+ attributes that a PCI root bridge is currently using.
+
+ The GetAttributes() function returns the mask of attributes that this PCI root bridge supports
+ and the mask of attributes that the PCI root bridge is currently using.
+
+ @param This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param Supported A pointer to the mask of attributes that this PCI root bridge
+ supports setting with SetAttributes().
+ @param Attributes A pointer to the mask of attributes that this PCI root bridge is
+ currently using.
+
+ @retval EFI_SUCCESS If Supports is not NULL, then the attributes that the PCI root
+ bridge supports is returned in Supports. If Attributes is
+ not NULL, then the attributes that the PCI root bridge is currently
+ using is returned in Attributes.
+ @retval EFI_INVALID_PARAMETER Both Supports and Attributes are NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoGetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT UINT64 *Supported,
+ OUT UINT64 *Attributes
+ );
+
+/**
+ Sets attributes for a resource range on a PCI root bridge.
+
+ The SetAttributes() function sets the attributes specified in Attributes for the PCI root
+ bridge on the resource range specified by ResourceBase and ResourceLength. Since the
+ granularity of setting these attributes may vary from resource type to resource type, and from
+ platform to platform, the actual resource range and the one passed in by the caller may differ. As a
+ result, this function may set the attributes specified by Attributes on a larger resource range
+ than the caller requested. The actual range is returned in ResourceBase and
+ ResourceLength. The caller is responsible for verifying that the actual range for which the
+ attributes were set is acceptable.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[in] Attributes The mask of attributes to set. If the attribute bit
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, or
+ MEMORY_DISABLE is set, then the resource range is specified by
+ ResourceBase and ResourceLength. If
+ MEMORY_WRITE_COMBINE, MEMORY_CACHED, and
+ MEMORY_DISABLE are not set, then ResourceBase and
+ ResourceLength are ignored, and may be NULL.
+ @param[in, out] ResourceBase A pointer to the base address of the resource range to be modified
+ by the attributes specified by Attributes.
+ @param[in, out] ResourceLength A pointer to the length of the resource range to be modified by the
+ attributes specified by Attributes.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoSetAttributes (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ IN UINT64 Attributes,
+ IN OUT UINT64 *ResourceBase,
+ IN OUT UINT64 *ResourceLength
+ );
+
+/**
+ Retrieves the current resource settings of this PCI root bridge in the form of a set of ACPI 2.0
+ resource descriptors.
+
+ There are only two resource descriptor types from the ACPI Specification that may be used to
+ describe the current resources allocated to a PCI root bridge. These are the QWORD Address
+ Space Descriptor (ACPI 2.0 Section 6.4.3.5.1), and the End Tag (ACPI 2.0 Section 6.4.2.8). The
+ QWORD Address Space Descriptor can describe memory, I/O, and bus number ranges for dynamic
+ or fixed resources. The configuration of a PCI root bridge is described with one or more QWORD
+ Address Space Descriptors followed by an End Tag.
+
+ @param[in] This A pointer to the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.
+ @param[out] Resources A pointer to the ACPI 2.0 resource descriptors that describe the
+ current configuration of this PCI root bridge. The storage for the
+ ACPI 2.0 resource descriptors is allocated by this function. The
+ caller must treat the return buffer as read-only data, and the buffer
+ must not be freed by the caller.
+
+ @retval EFI_SUCCESS The current configuration of this PCI root bridge was returned in Resources.
+ @retval EFI_UNSUPPORTED The current configuration of this PCI root bridge could not be retrieved.
+ @retval EFI_INVALID_PARAMETER Invalid pointer of EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL
+
+**/
+EFI_STATUS
+EFIAPI
+RootBridgeIoConfiguration (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *This,
+ OUT VOID **Resources
+ );
+
+// Structure for PCI region
+typedef struct {
+ PciAddrT BusStart; // Start on the bus
+ PhysAddrT PhysStart; // Start in physical address space
+ PciSizeT Size; // Size
+ UINT64 Flags; // Resource flags
+ PciAddrT BusLower;
+} PciRegion;
+
+// Structure for PCI space(I/O,Mem,Configuration)
+typedef struct {
+ UINT64 Regs;
+ INT32 PciNum;
+ UINT64 Cfg0Phys;
+ UINT64 Cfg0Size;
+ UINT64 Cfg1Phys;
+ UINT64 Cfg1Size;
+ UINT64 MemBus;
+ UINT64 MemPhys;
+ UINT64 MemSize;
+ UINT64 IoBus;
+ UINT64 IoPhys;
+ UINT64 IoSize;
+} LsPcieInfo;
+
+typedef struct {
+ INTN Idx;
+ VOID *Dbi;
+ UINT32 *VaCfg0;
+ UINT32 *VaCfg1;
+} LsPcie;
+
+typedef struct {
+ UINTN Vendor, Device; // Vendor and device ID or PCI_ANY_ID
+} PciDeviceId;
+
+typedef struct {
+ UINTN Vendor, Device; // Vendor and device ID or PCI_ANY_ID
+ UINTN Class; // Class ID, or PCI_ANY_ID
+ UINTN Bus; // Bus number, or PCI_ANY_ID
+ UINTN Dev; // Device number, or PCI_ANY_ID
+ UINTN Func; // Function number, or PCI_ANY_ID
+ UINTN Priv[3];
+} PciConfigTable;
+
+#define ACPI_SPECFLAG_PREFETCHABLE 0x06
+#define EFI_RESOURCE_NONEXISTENT 0xFFFFFFFFFFFFFFFFULL
+#define EFI_RESOURCE_LESS 0xFFFFFFFFFFFFFFFEULL
+
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+
+typedef enum {
+ ResTypeIo = 0,
+ ResTypeMem32,
+ ResTypePMem32,
+ ResTypeMem64,
+ ResTypePMem64,
+ ResTypeMax
+} PCI_RESOURCE_TYPE;
+
+typedef struct {
+ UINT64 Base;
+ UINT64 Length;
+ UINT64 Alignment;
+} PCI_RESOURCE_ALLOC;
+
+typedef struct {
+ UINTN Signature;
+ LIST_ENTRY Link;
+ EFI_HANDLE Handle;
+ UINT64 RootBridgeAttrib;
+ UINT64 Attributes;
+ UINT64 Supports;
+ UINTN BusStart;
+ UINTN BusLength;
+ UINT64 MemAllocAttributes;
+ PCI_RESOURCE_ALLOC ResAlloc[ResTypeMax];
+ UINT64 PciBaseAddress64;
+ UINT64 PciMemBase64;
+ LsPcieInfo *Info;
+ LsPcie *Pcie;
+ struct PCI_ROOT_BRIDGE_INSTANCE *Next;
+ INTN FirstBusno;
+ INTN LastBusno;
+ INTN CurrentBusno;
+ UINTN *CfgAddr;
+ CHAR8 *CfgData;
+ INTN IndirectType;
+ PciRegion Regions[MAX_PCI_REGIONS];
+ INTN RegionCnt;
+ PciConfigTable *ConfigTable;
+
+ PciRegion *PciMem, *PciIo, *PciPrefetch;
+
+ EFI_PCI_ROOT_BRIDGE_DEVICE_PATH DevicePath;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL Io;
+
+} PCI_ROOT_BRIDGE_INSTANCE;
+
+#endif
--
1.9.1
^ permalink raw reply related [flat|nested] 7+ messages in thread