new file mode 100644
@@ -0,0 +1,225 @@
+/** @file
+ PCI Host Bridge Library instance for Socionext SynQuacer ARM SOC
+
+ Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+
+ 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.
+
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/DebugLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Platform/Pcie.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#pragma pack(1)
+typedef struct {
+ ACPI_HID_DEVICE_PATH AcpiDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL EndDevicePath;
+} EFI_PCI_ROOT_BRIDGE_DEVICE_PATH;
+#pragma pack ()
+
+STATIC CONST 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 (0x0A08), // PCI Express
+ 0
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ },
+ {
+ {
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ {
+ (UINT8)(sizeof(ACPI_HID_DEVICE_PATH)),
+ (UINT8)(sizeof(ACPI_HID_DEVICE_PATH) >> 8)
+ }
+ },
+ EISA_PNP_ID (0x0A08), // PCI Express
+ 1
+ },
+
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ END_DEVICE_PATH_LENGTH,
+ 0
+ }
+ }
+ }
+};
+
+GLOBAL_REMOVE_IF_UNREFERENCED
+CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = {
+ L"Mem", L"I/O", L"Bus"
+};
+
+#ifndef MDE_CPU_ARM
+#define PCI_ALLOCATION_ATTRIBUTES EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | \
+ EFI_PCI_HOST_BRIDGE_MEM64_DECODE
+#else
+#define PCI_ALLOCATION_ATTRIBUTES EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM
+#endif
+
+STATIC PCI_ROOT_BRIDGE mPciRootBridges[] = {
+ {
+ 0, // Segment
+ 0, // Supports
+ 0, // Attributes
+ TRUE, // DmaAbove4G
+ FALSE, // NoExtendedConfigSpace
+ FALSE, // ResourceAssigned
+ PCI_ALLOCATION_ATTRIBUTES, // AllocationAttributes
+ { SYNQUACER_PCI_SEG0_BUSNUM_MIN,
+ SYNQUACER_PCI_SEG0_BUSNUM_MAX }, // Bus
+ { SYNQUACER_PCI_SEG0_PORTIO_MIN,
+ SYNQUACER_PCI_SEG0_PORTIO_MAX }, // Io
+ { SYNQUACER_PCI_SEG0_MMIO32_MIN,
+ SYNQUACER_PCI_SEG0_MMIO32_MAX }, // Mem
+ { SYNQUACER_PCI_SEG0_MMIO64_MIN,
+ SYNQUACER_PCI_SEG0_MMIO64_MAX }, // MemAbove4G
+ { MAX_UINT64, 0x0 }, // PMem
+ { MAX_UINT64, 0x0 }, // PMemAbove4G
+ (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[0]
+ }, {
+ 1, // Segment
+ 0, // Supports
+ 0, // Attributes
+ TRUE, // DmaAbove4G
+ FALSE, // NoExtendedConfigSpace
+ FALSE, // ResourceAssigned
+ PCI_ALLOCATION_ATTRIBUTES, // AllocationAttributes
+ { SYNQUACER_PCI_SEG1_BUSNUM_MIN,
+ SYNQUACER_PCI_SEG1_BUSNUM_MAX }, // Bus
+ { SYNQUACER_PCI_SEG1_PORTIO_MIN,
+ SYNQUACER_PCI_SEG1_PORTIO_MAX }, // Io
+ { SYNQUACER_PCI_SEG1_MMIO32_MIN,
+ SYNQUACER_PCI_SEG1_MMIO32_MAX }, // Mem
+ { SYNQUACER_PCI_SEG1_MMIO64_MIN,
+ SYNQUACER_PCI_SEG1_MMIO64_MAX }, // MemAbove4G
+ { MAX_UINT64, 0x0 }, // PMem
+ { MAX_UINT64, 0x0 }, // PMemAbove4G
+ (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath[1]
+ }
+};
+
+/**
+ Return all the root bridge instances in an array.
+
+ @param Count Return the count of root bridge instances.
+
+ @return All the root bridge instances in an array.
+ The array should be passed into PciHostBridgeFreeRootBridges()
+ when it's not used.
+**/
+PCI_ROOT_BRIDGE *
+EFIAPI
+PciHostBridgeGetRootBridges (
+ OUT UINTN *Count
+ )
+{
+ *Count = ARRAY_SIZE (mPciRootBridges);
+
+ return mPciRootBridges;
+}
+
+/**
+ Free the root bridge instances array returned from PciHostBridgeGetRootBridges().
+
+ @param Bridges The root bridge instances array.
+ @param Count The count of the array.
+**/
+VOID
+EFIAPI
+PciHostBridgeFreeRootBridges (
+ PCI_ROOT_BRIDGE *Bridges,
+ UINTN Count
+ )
+{
+}
+
+/**
+ Inform the platform that the resource conflict happens.
+
+ @param HostBridgeHandle Handle of the Host Bridge.
+ @param Configuration Pointer to PCI I/O and PCI memory resource
+ descriptors. The Configuration contains the resources
+ for all the root bridges. The resource for each root
+ bridge is terminated with END descriptor and an
+ additional END is appended indicating the end of the
+ entire resources. The resource descriptor field
+ values follow the description in
+ EFI_PCI_HOST_BRIDGE_RESOURCE_ALLOCATION_PROTOCOL
+ .SubmitResources().
+**/
+VOID
+EFIAPI
+PciHostBridgeResourceConflict (
+ EFI_HANDLE HostBridgeHandle,
+ VOID *Configuration
+ )
+{
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
+ UINTN RootBridgeIndex;
+ DEBUG ((DEBUG_ERROR, "PciHostBridge: Resource conflict happens!\n"));
+
+ RootBridgeIndex = 0;
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *) Configuration;
+ while (Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ DEBUG ((DEBUG_ERROR, "RootBridge[%d]:\n", RootBridgeIndex++));
+ for (; Descriptor->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR; Descriptor++) {
+ ASSERT (Descriptor->ResType <
+ ARRAY_SIZE (mPciHostBridgeLibAcpiAddressSpaceTypeStr));
+ DEBUG ((DEBUG_ERROR, " %s: Length/Alignment = 0x%lx / 0x%lx\n",
+ mPciHostBridgeLibAcpiAddressSpaceTypeStr[Descriptor->ResType],
+ Descriptor->AddrLen, Descriptor->AddrRangeMax
+ ));
+ if (Descriptor->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) {
+ DEBUG ((DEBUG_ERROR, " Granularity/SpecificFlag = %ld / %02x%s\n",
+ Descriptor->AddrSpaceGranularity, Descriptor->SpecificFlag,
+ ((Descriptor->SpecificFlag &
+ EFI_ACPI_MEMORY_RESOURCE_SPECIFIC_FLAG_CACHEABLE_PREFETCHABLE
+ ) != 0) ? L" (Prefetchable)" : L""
+ ));
+ }
+ }
+ //
+ // Skip the END descriptor for root bridge
+ //
+ ASSERT (Descriptor->Desc == ACPI_END_TAG_DESCRIPTOR);
+ Descriptor = (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *)(
+ (EFI_ACPI_END_TAG_DESCRIPTOR *)Descriptor + 1
+ );
+ }
+}
new file mode 100644
@@ -0,0 +1,50 @@
+## @file
+# PCI Host Bridge Library instance for Socionext SynQuacer ARM SOC
+#
+# Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+#
+# 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 = 0x00010019
+ BASE_NAME = SynQuacerPciHostBridgeLib
+ FILE_GUID = fdc92446-65bc-4f86-b4a0-014a2119a732
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = PciHostBridgeLib|DXE_DRIVER
+ CONSTRUCTOR = SynQuacerPciHostBridgeLibConstructor
+
+#
+# The following information is for reference only and not required by the build
+# tools.
+#
+# VALID_ARCHITECTURES = ARM AARCH64
+#
+
+[Sources]
+ SynQuacerPciHostBridgeLib.c
+ SynQuacerPciHostBridgeLibConstructor.c
+
+[Packages]
+ ArmPkg/ArmPkg.dec
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ Silicon/Socionext/SynQuacer/SynQuacer.dec
+
+[LibraryClasses]
+ ArmLib
+ DebugLib
+ DevicePathLib
+ MemoryAllocationLib
+
+[FixedPcd]
+ gArmTokenSpaceGuid.PcdPciIoTranslation
new file mode 100644
@@ -0,0 +1,390 @@
+/** @file
+ PCI Host Bridge Library instance for Socionext SynQuacer ARM SOC
+
+ Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR>
+
+ 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.
+
+**/
+
+#include <PiDxe.h>
+#include <IndustryStandard/Pci22.h>
+#include <Library/ArmLib.h>
+#include <Library/DebugLib.h>
+#include <Library/IoLib.h>
+#include <Library/PciHostBridgeLib.h>
+#include <Platform/Pcie.h>
+#include <Protocol/PciHostBridgeResourceAllocation.h>
+
+#define IATU_VIEWPORT_OFF 0x900
+#define IATU_VIEWPORT_INBOUND BIT31
+#define IATU_VIEWPORT_OUTBOUND 0
+#define IATU_VIEWPORT_REGION_INDEX(Idx) ((Idx) & 7)
+
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0 0x904
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM 0x0
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO 0x2
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0 0x4
+#define IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1 0x5
+
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0 0x908
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN BIT31
+#define IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE BIT28
+
+#define IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0 0x90C
+#define IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0 0x910
+#define IATU_LIMIT_ADDR_OFF_OUTBOUND_0 0x914
+#define IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0 0x918
+#define IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0 0x91C
+
+#define CORE_CONTROL 0x000
+#define APP_LTSSM_ENABLE BIT4
+#define DEVICE_TYPE (BIT3 | BIT2 | BIT1 | BIT0)
+
+#define AXI_CLK_STOP 0x004
+#define DBI_ACLK_STOP BIT8
+#define SLV_ACLK_STOP BIT4
+#define MSTR_ACLK_STOP BIT0
+#define DBI_CSYSREQ_REG BIT9
+#define SLV_CSYSREQ_REG BIT5
+#define MSTR_CSYSREQ_REG BIT1
+
+#define RESET_CONTROL_1 0x00C
+#define PERST_N_O_REG BIT5
+#define PERST_N_I_REG BIT4
+#define BUTTON_RST_N_REG BIT1
+#define PWUP_RST_N_REG BIT0
+
+#define RESET_CONTROL_2 0x010
+
+#define RESET_SELECT_1 0x014
+#define SQU_RST_SEL BIT29
+#define PHY_RST_SEL BIT28
+#define PWR_RST_SEL BIT24
+#define STI_RST_SEL BIT20
+#define N_STI_RST_SEL BIT16
+#define CORE_RST_SEL BIT12
+#define PERST_SEL BIT4
+#define BUTTON_RST_SEL BIT1
+#define PWUP_RST_SEL BIT0
+
+#define RESET_SELECT_2 0x018
+#define DBI_ARST_SEL BIT8
+#define SLV_ARST_SEL BIT4
+#define MSTR_ARST_SEL BIT0
+
+#define EM_CONTROL 0x030
+#define PRE_DET_STT_REG BIT4
+
+#define EM_SELECT 0x034
+#define PRE_DET_STT_SEL BIT4
+
+#define PM_CONTROL_2 0x050
+#define SYS_AUX_PWR_DET BIT8
+
+#define PHY_CONFIG_COM_6 0x114
+#define PIPE_PORT_SEL (BIT1 | BIT0)
+
+#define LINK_MONITOR 0x210
+#define SMLH_LINK_UP BIT0
+
+#define LINK_CAPABILITIES_REG 0x07C
+#define PCIE_CAP_MAX_LINK_WIDTH (BIT7 | BIT6 | BIT5 | BIT4)
+#define PCIE_CAP_MAX_LINK_SPEED (BIT3 | BIT2 | BIT1 | BIT0)
+
+#define LINK_CONTROL_LINK_STATUS_REG 0x080
+#define PCIE_CAP_NEGO_LINK_WIDTH (BIT23 | BIT22 | BIT21 | BIT20)
+#define PCIE_CAP_LINK_SPEED (BIT19 | BIT18 | BIT17 | BIT16)
+
+#define TYPE1_CLASS_CODE_REV_ID_REG 0x008
+#define BASE_CLASS_CODE 0xFF000000
+#define BASE_CLASS_CODE_VALUE 0x06
+#define SUBCLASS_CODE 0x00FF0000
+#define SUBCLASS_CODE_VALUE 0x04
+#define PROGRAM_INTERFACE 0x0000FF00
+#define PROGRAM_INTERFACE_VALUE 0x00
+
+#define MISC_CONTROL_1_OFF 0x8BC
+#define DBI_RO_WR_EN BIT0
+
+STATIC
+VOID
+ConfigureWindow (
+ IN EFI_PHYSICAL_ADDRESS DbiBase,
+ IN UINTN Index,
+ IN UINT64 CpuBase,
+ IN UINT64 PciBase,
+ IN UINT64 Size,
+ IN UINTN Type,
+ IN UINTN EnableFlags
+ )
+{
+ ArmDataMemoryBarrier ();
+
+ MmioWrite32 (DbiBase + IATU_VIEWPORT_OFF,
+ IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index));
+
+ ArmDataMemoryBarrier ();
+
+ MmioWrite32 (DbiBase + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0,
+ (UINT32)(CpuBase & 0xFFFFFFFF));
+ MmioWrite32 (DbiBase + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0,
+ (UINT32)(CpuBase >> 32));
+ MmioWrite32 (DbiBase + IATU_LIMIT_ADDR_OFF_OUTBOUND_0,
+ (UINT32)(CpuBase + Size - 1));
+ MmioWrite32 (DbiBase + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0,
+ (UINT32)(PciBase & 0xFFFFFFFF));
+ MmioWrite32 (DbiBase + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0,
+ (UINT32)(PciBase >> 32));
+ MmioWrite32 (DbiBase + IATU_REGION_CTRL_1_OFF_OUTBOUND_0,
+ Type);
+ MmioWrite32 (DbiBase + IATU_REGION_CTRL_2_OFF_OUTBOUND_0,
+ IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags);
+}
+
+STATIC
+VOID
+SnPcieSetData (
+ EFI_PHYSICAL_ADDRESS Base,
+ UINT32 Offset,
+ UINT32 Mask,
+ UINT32 In
+ )
+{
+ UINT32 Data;
+ UINT32 Shift;
+
+ Shift = 1;
+ if (In) {
+ while (!(Mask & Shift))
+ Shift <<= 1;
+ Data = (MmioRead32 (Base + Offset) & ~Mask) | (In * Shift);
+ } else {
+ Data = MmioRead32 (Base + Offset) & ~Mask;
+ }
+
+ MmioWrite32 (Base + Offset, Data);
+}
+
+STATIC
+UINT32
+SnPcieReadData (
+ EFI_PHYSICAL_ADDRESS Base,
+ UINT32 Offset,
+ UINT32 Mask
+ )
+{
+ UINT32 Shift;
+
+ Shift = 0;
+ while (!(Mask & 1)) {
+ Mask >>= 1;
+ Shift++;
+ }
+
+ return (MmioRead32 (Base + Offset) >> Shift) & Mask;
+}
+
+STATIC
+VOID
+SnDbiRoWrEn (
+ IN EFI_PHYSICAL_ADDRESS DbiBase,
+ IN INTN MaxLinkWidth,
+ IN INTN MaxLinkSpeed
+ )
+{
+ SnPcieSetData (DbiBase, MISC_CONTROL_1_OFF, DBI_RO_WR_EN, 1);
+
+ SnPcieSetData (DbiBase, LINK_CAPABILITIES_REG, PCIE_CAP_MAX_LINK_WIDTH, MaxLinkWidth);
+ SnPcieSetData (DbiBase, LINK_CAPABILITIES_REG, PCIE_CAP_MAX_LINK_SPEED, MaxLinkSpeed);
+
+ SnPcieSetData (DbiBase, TYPE1_CLASS_CODE_REV_ID_REG, BASE_CLASS_CODE, BASE_CLASS_CODE_VALUE);
+ SnPcieSetData (DbiBase, TYPE1_CLASS_CODE_REV_ID_REG, SUBCLASS_CODE, SUBCLASS_CODE_VALUE);
+ SnPcieSetData (DbiBase, TYPE1_CLASS_CODE_REV_ID_REG, PROGRAM_INTERFACE, PROGRAM_INTERFACE_VALUE);
+
+ SnPcieSetData (DbiBase, MISC_CONTROL_1_OFF, DBI_RO_WR_EN, 0);
+}
+
+STATIC
+VOID
+PciInitController (
+ IN EFI_PHYSICAL_ADDRESS ExsBase,
+ IN EFI_PHYSICAL_ADDRESS DbiBase,
+ IN EFI_PHYSICAL_ADDRESS ConfigBase,
+ IN EFI_PHYSICAL_ADDRESS IoMemBase,
+ IN CONST PCI_ROOT_BRIDGE *RootBridge
+ )
+{
+ SnPcieSetData (ExsBase, EM_SELECT, PRE_DET_STT_SEL, 0);
+ SnPcieSetData (ExsBase, EM_CONTROL, PRE_DET_STT_REG, 0);
+ SnPcieSetData (ExsBase, EM_CONTROL, PRE_DET_STT_REG, 1);
+
+ // 1: Assert all PHY / LINK resets
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , PERST_SEL , 0);
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, PERST_N_I_REG , 0);
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, PERST_N_O_REG , 0);
+
+ // Device Reset(PERST#) is effective afrer Set device_type (RC)
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , PWUP_RST_SEL , 0);
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, PWUP_RST_N_REG, 0);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , BUTTON_RST_SEL , 0);
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, BUTTON_RST_N_REG, 0);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , PWR_RST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_2 , MSTR_ARST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_2 , SLV_ARST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_2 , DBI_ARST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , CORE_RST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , STI_RST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , N_STI_RST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , SQU_RST_SEL , 1);
+ SnPcieSetData (ExsBase, RESET_SELECT_1 , PHY_RST_SEL , 1);
+
+ // 2: Set P<n>_app_ltssm_enable='0' for reprogramming before linkup.
+ SnPcieSetData (ExsBase, CORE_CONTROL, APP_LTSSM_ENABLE, 0);
+
+ // 3: Set device_type (RC)
+ SnPcieSetData (ExsBase, CORE_CONTROL, DEVICE_TYPE, 4);
+
+ // 4: Set Bifurcation 1=disable 4=able
+ // 5: Supply Reference (It has executed)
+ // 6: Wait for 10usec (Reference Clocks is stable)
+ // 7 De assert PERST# */
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, PERST_N_I_REG, 1);
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, PERST_N_O_REG, 1);
+
+ // 8 Assert SYS_AUX_PWR_DET
+ SnPcieSetData(ExsBase, PM_CONTROL_2, SYS_AUX_PWR_DET, 1);
+
+ // 9 Supply following clocks
+ SnPcieSetData (ExsBase, AXI_CLK_STOP, MSTR_CSYSREQ_REG, 1);
+ SnPcieSetData (ExsBase, AXI_CLK_STOP, MSTR_ACLK_STOP, 0);
+ SnPcieSetData (ExsBase, AXI_CLK_STOP, SLV_CSYSREQ_REG, 1);
+ SnPcieSetData (ExsBase, AXI_CLK_STOP, SLV_ACLK_STOP, 0);
+ SnPcieSetData (ExsBase, AXI_CLK_STOP, DBI_CSYSREQ_REG, 1);
+ SnPcieSetData (ExsBase, AXI_CLK_STOP, DBI_ACLK_STOP, 0);
+
+ // 10 De assert PHY reset
+ // 11 De assert LINK's PMC reset
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, PWUP_RST_N_REG, 1);
+ SnPcieSetData (ExsBase, RESET_CONTROL_1, BUTTON_RST_N_REG, 1);
+ // 12 PHY auto
+ // 13 Wrapper auto
+ // 14-17 PHY auto
+ // 18 Wrapper auto
+ // 19 Update registers through DBI AXI Slave interface
+ SnDbiRoWrEn (DbiBase, 4 /* lanes */, /* Gen */ 2);
+
+ //
+ // ECAM shift mode uses bits [27:12] of the untranslated address as
+ // B/D/F identifiers. This only works as expected if the base of the
+ // region is aligned to 256 MB, or the effective bus numbers will be
+ // out of sync with the bus base and limit values we chose.
+ //
+ ASSERT ((ConfigBase % SIZE_256MB) == RootBridge->Bus.Base * SIZE_1MB);
+
+ MmioOr32 (DbiBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_IO_SPACE |
+ EFI_PCI_COMMAND_MEMORY_SPACE |
+ EFI_PCI_COMMAND_BUS_MASTER);
+
+ // Region 0: MMIO32 range
+ ConfigureWindow (DbiBase, 0,
+ RootBridge->Mem.Base,
+ RootBridge->Mem.Base,
+ RootBridge->Mem.Limit - RootBridge->Mem.Base + 1,
+ IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+ 0);
+
+ // Region 1: Type 0 config space
+ ConfigureWindow (DbiBase, 1,
+ ConfigBase + RootBridge->Bus.Base * SIZE_1MB,
+ 0x0,
+ SIZE_64KB,
+ IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG0,
+ IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
+
+ // Region 2: Type 1 config space
+ ConfigureWindow (DbiBase, 2,
+ ConfigBase + RootBridge->Bus.Base * SIZE_1MB + SIZE_64KB,
+ 0x0,
+ (RootBridge->Bus.Limit - RootBridge->Bus.Base + 1) * SIZE_1MB - SIZE_64KB,
+ IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_CFG1,
+ IATU_REGION_CTRL_2_OFF_OUTBOUND_0_CFG_SHIFT_MODE);
+
+ // Region 3: port I/O range
+ ConfigureWindow (DbiBase, 3,
+ IoMemBase,
+ RootBridge->Io.Base,
+ RootBridge->Io.Limit - RootBridge->Io.Base + 1,
+ IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO,
+ 0);
+
+ // Region 4: MMIO64 range
+ if (RootBridge->AllocationAttributes & EFI_PCI_HOST_BRIDGE_MEM64_DECODE) {
+ ConfigureWindow (DbiBase, 4,
+ RootBridge->MemAbove4G.Base,
+ RootBridge->MemAbove4G.Base,
+ RootBridge->MemAbove4G.Limit - RootBridge->MemAbove4G.Base + 1,
+ IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM,
+ 0);
+ }
+
+ // enable link
+ if (SnPcieReadData (ExsBase, CORE_CONTROL, APP_LTSSM_ENABLE) == 0) {
+ SnPcieSetData (ExsBase, CORE_CONTROL, APP_LTSSM_ENABLE, 1);
+ }
+}
+
+STATIC CONST struct {
+ EFI_PHYSICAL_ADDRESS DbiBase;
+ EFI_PHYSICAL_ADDRESS ExsBase;
+ EFI_PHYSICAL_ADDRESS ConfigBase;
+ EFI_PHYSICAL_ADDRESS IoMemBase;
+} mBaseAddresses [] = {
+ {
+ SYNQUACER_PCI_SEG0_DBI_BASE,
+ SYNQUACER_PCI_SEG0_EXS_BASE,
+ SYNQUACER_PCI_SEG0_CONFIG_BASE,
+ SYNQUACER_PCI_SEG0_PORTIO_MEMBASE
+ },
+ {
+ SYNQUACER_PCI_SEG1_DBI_BASE,
+ SYNQUACER_PCI_SEG1_EXS_BASE,
+ SYNQUACER_PCI_SEG1_CONFIG_BASE,
+ SYNQUACER_PCI_SEG1_PORTIO_MEMBASE
+ },
+};
+
+
+EFI_STATUS
+EFIAPI
+SynQuacerPciHostBridgeLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ PCI_ROOT_BRIDGE *RootBridges;
+ UINTN Count;
+ UINTN Idx;
+
+ RootBridges = PciHostBridgeGetRootBridges (&Count);
+ ASSERT (Count == ARRAY_SIZE(mBaseAddresses));
+ if (Count != ARRAY_SIZE(mBaseAddresses)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for (Idx = 0; Idx < Count; Idx++) {
+ PciInitController (mBaseAddresses[Idx].ExsBase,
+ mBaseAddresses[Idx].DbiBase,
+ mBaseAddresses[Idx].ConfigBase,
+ mBaseAddresses[Idx].IoMemBase,
+ &RootBridges[Idx]);
+ }
+
+ return EFI_SUCCESS;
+}