Add an implementation of the PciHostBridgeLib glue library that describes the PCIe RC on this SoC so that the generic PCI host bridge driver can attach to it.
This includes a constructor which performs the SoC specific init and training sequences. This patch is based on work of Ard Biesheuvel <ard.biesheu...@linaro.org> and Jing Hua <jing...@marvell.com>/ Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Marcin Wojtas <m...@semihalf.com> --- Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf | 52 +++ Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h | 95 ++++++ Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c | 244 +++++++++++++++ Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c | 330 ++++++++++++++++++++ 4 files changed, 721 insertions(+) create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c create mode 100644 Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf new file mode 100644 index 0000000..e46f71d --- /dev/null +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.inf @@ -0,0 +1,52 @@ +## @file +# PCI Host Bridge Library instance for Marvell Armada 7k/8k SOC +# +# Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR> +# Copyright (c) 2019 Marvell International 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 = 0x0001001B + BASE_NAME = Armada7k8kPciHostBridgeLib + FILE_GUID = 7f989c9d-02a0-4348-8aeb-ab2e1566fb18 + MODULE_TYPE = DXE_DRIVER + VERSION_STRING = 1.0 + LIBRARY_CLASS = PciHostBridgeLib|DXE_DRIVER + CONSTRUCTOR = Armada7k8kPciHostBridgeLibConstructor + +[Sources] + PciHostBridgeLib.c + PciHostBridgeLibConstructor.c + +[Packages] + ArmPkg/ArmPkg.dec + EmbeddedPkg/EmbeddedPkg.dec + MdeModulePkg/MdeModulePkg.dec + MdePkg/MdePkg.dec + Silicon/Marvell/Marvell.dec + +[LibraryClasses] + ArmLib + ArmadaSoCDescLib + DebugLib + DevicePathLib + MemoryAllocationLib + MvGpioLib + UefiBootServicesTableLib + +[Protocols] + gEmbeddedGpioProtocolGuid + gMarvellBoardDescProtocolGuid + +[Depex] + gMarvellPlatformInitCompleteProtocolGuid diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h new file mode 100644 index 0000000..ff9d919 --- /dev/null +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h @@ -0,0 +1,95 @@ +/** @file + PCI Host Bridge Library instance for Marvell 70x0/80x0 + + Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR> + Copyright (c) 2019 Marvell International 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. + +**/ +#ifndef __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_H__ +#define __PCI_HOST_BRIDGE_LIB_CONSTRUCTOR_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 PORT_LINK_CTRL_OFF 0x710 +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x1 (0x01 << 16) +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x2 (0x03 << 16) +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4 (0x07 << 16) +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x8 (0x0f << 16) +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_x16 (0x1f << 16) +#define PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK (0x3f << 16) + +#define GEN2_CTRL_OFF 0x80c +#define GEN2_CTRL_OFF_NUM_OF_LANES(n) (((n) & 0x1f) << 8) +#define GEN2_CTRL_OFF_NUM_OF_LANES_MASK (0x1f << 8) +#define GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE BIT17 + +#define PCIE_GLOBAL_CTRL_OFFSET 0x8000 +#define PCIE_GLOBAL_APP_LTSSM_EN BIT2 +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC (0x4 << 4) +#define PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK (0xF << 4) + +#define PCIE_GLOBAL_STATUS_REG 0x8008 +#define PCIE_GLOBAL_STATUS_RDLH_LINK_UP BIT1 +#define PCIE_GLOBAL_STATUS_PHY_LINK_UP BIT9 + +#define PCIE_PM_STATUS 0x8014 +#define PCIE_PM_LTSSM_STAT_MASK (0x3f << 3) + +#define PCIE_GLOBAL_INT_MASK1_REG 0x8020 +#define PCIE_INT_A_ASSERT_MASK BIT9 +#define PCIE_INT_B_ASSERT_MASK BIT10 +#define PCIE_INT_C_ASSERT_MASK BIT11 +#define PCIE_INT_D_ASSERT_MASK BIT12 + +#define PCIE_ARCACHE_TRC_REG 0x8050 +#define PCIE_AWCACHE_TRC_REG 0x8054 +#define PCIE_ARUSER_REG 0x805C +#define PCIE_AWUSER_REG 0x8060 + +#define ARCACHE_DEFAULT_VALUE 0x3511 +#define AWCACHE_DEFAULT_VALUE 0x5311 + +#define AX_USER_DOMAIN_INNER_SHAREABLE (0x1 << 4) +#define AX_USER_DOMAIN_OUTER_SHAREABLE (0x2 << 4) +#define AX_USER_DOMAIN_MASK (0x3 << 4) + +#define PCIE_LINK_CAPABILITY 0x7C +#define PCIE_LINK_CTL_2 0xA0 +#define TARGET_LINK_SPEED_MASK 0xF +#define LINK_SPEED_GEN_1 0x1 +#define LINK_SPEED_GEN_2 0x2 +#define LINK_SPEED_GEN_3 0x3 + +#define PCIE_GEN3_EQU_CTRL 0x8A8 +#define GEN3_EQU_EVAL_2MS_DISABLE BIT5 + +#define PCIE_LINK_UP_TIMEOUT_US 40000 + +#endif diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c new file mode 100644 index 0000000..ff6288c --- /dev/null +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLib.c @@ -0,0 +1,244 @@ +/** @file + PCI Host Bridge Library instance for Marvell Armada 70x0/80x0 + + Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR> + Copyright (c) 2019 Marvell International 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 <Library/DebugLib.h> +#include <Library/DevicePathLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/PcdLib.h> +#include <Library/PciHostBridgeLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/BoardDesc.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 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 + } + } +}; + +GLOBAL_REMOVE_IF_UNREFERENCED +CHAR16 *mPciHostBridgeLibAcpiAddressSpaceTypeStr[] = { + L"Mem", L"I/O", L"Bus" +}; + +/** + 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 ( + UINTN *Count + ) +{ + MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol; + MV_BOARD_PCIE_DESCRIPTION *BoardPcieDescription; + MV_PCIE_CONTROLLER *PcieController; + PCI_ROOT_BRIDGE *PciRootBridges; + PCI_ROOT_BRIDGE *RootBridge; + EFI_STATUS Status; + UINTN Index; + + *Count = 0; + + /* Obtain list of available controllers */ + Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid, + NULL, + (VOID **)&BoardDescriptionProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: Cannot locate BoardDesc protocol\n", + __FUNCTION__)); + return NULL; + } + + Status = BoardDescriptionProtocol->PcieDescriptionGet ( + BoardDescriptionProtocol, + &BoardPcieDescription); + if (Status == EFI_NOT_FOUND) { + /* No controllers used on the platform, exit silently */ + return NULL; + } else if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: Cannot get Pcie board desc from BoardDesc protocol\n", + __FUNCTION__)); + return NULL; + } + + /* Assign return values */ + PciRootBridges = AllocateZeroPool (BoardPcieDescription->PcieControllerCount * + sizeof (PCI_ROOT_BRIDGE)); + if (PciRootBridges == NULL) { + DEBUG ((DEBUG_ERROR, "%a: Fail to allocate resources\n", __FUNCTION__)); + return NULL; + } + + *Count = BoardPcieDescription->PcieControllerCount; + RootBridge = PciRootBridges; + + /* Fill information of all root bridge instances */ + for (Index = 0; Index < *Count; Index++, RootBridge++) { + + PcieController = &(BoardPcieDescription->PcieControllers[Index]); + + RootBridge->Segment = 0; + RootBridge->Supports = 0; + RootBridge->Attributes = RootBridge->Supports; + + RootBridge->DmaAbove4G = FALSE; + + RootBridge->AllocationAttributes = EFI_PCI_HOST_BRIDGE_COMBINE_MEM_PMEM | + EFI_PCI_HOST_BRIDGE_MEM64_DECODE; + + RootBridge->Bus.Base = PcieController->PcieBusMin; + RootBridge->Bus.Limit = PcieController->PcieBusMax; + RootBridge->Io.Base = PcieController->PcieIoWinBase; + RootBridge->Io.Limit = PcieController->PcieIoWinBase + + PcieController->PcieIoWinSize - 1; + RootBridge->Mem.Base = PcieController->PcieMmio32WinBase; + RootBridge->Mem.Limit = PcieController->PcieMmio32WinBase + + PcieController->PcieMmio32WinSize - 1; + RootBridge->MemAbove4G.Base = PcieController->PcieMmio64WinBase; + RootBridge->MemAbove4G.Limit = PcieController->PcieMmio64WinBase + + PcieController->PcieMmio64WinSize - 1; + + /* No separate ranges for prefetchable and non-prefetchable BARs */ + RootBridge->PMem.Base = MAX_UINT64; + RootBridge->PMem.Limit = 0; + RootBridge->PMemAbove4G.Base = MAX_UINT64; + RootBridge->PMemAbove4G.Limit = 0; + + ASSERT (PcieController->PcieMmio64Translation == 0); + ASSERT (PcieController->PcieMmio32Translation == 0); + + RootBridge->NoExtendedConfigSpace = FALSE; + + RootBridge->DevicePath = (EFI_DEVICE_PATH_PROTOCOL *)&mEfiPciRootBridgeDevicePath; + } + + return PciRootBridges; +} + +/** + 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 + ) +{ + FreePool (Bridges); +} + +/** + 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 < + (sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr) / + sizeof (mPciHostBridgeLibAcpiAddressSpaceTypeStr[0]))); + + 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); + } +} diff --git a/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c new file mode 100644 index 0000000..ced2c12 --- /dev/null +++ b/Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.c @@ -0,0 +1,330 @@ +/** @file + PCI Host Bridge Library instance for Marvell 70x0/80x0 + + Copyright (c) 2017, Linaro Ltd. All rights reserved.<BR> + Copyright (c) 2019 Marvell International 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/MvGpioLib.h> +#include <Library/UefiBootServicesTableLib.h> + +#include <Protocol/BoardDesc.h> + +#include "PciHostBridgeLibConstructor.h" + +/** + This function configures PCIE controllers IATU windows. + + @param [in] PcieBaseAddress PCIE controller base address. + @param [in] Index IATU window index. + @param [in] CpuBase Address from the CPU perspective. + @param [in] PciBase Target PCIE address. + @param [in] Size IATU window size. + @param [in] Type IATU window type. + @param [in] EnableFlags Extra configuration flags. + + @retval none + +**/ +STATIC +VOID +ConfigureWindow ( + IN EFI_PHYSICAL_ADDRESS PcieBaseAddress, + IN UINTN Index, + IN UINT64 CpuBase, + IN UINT64 PciBase, + IN UINT64 Size, + IN UINTN Type, + IN UINTN EnableFlags + ) +{ + ArmDataMemoryBarrier (); + + MmioWrite32 (PcieBaseAddress + IATU_VIEWPORT_OFF, + IATU_VIEWPORT_OUTBOUND | IATU_VIEWPORT_REGION_INDEX (Index)); + + ArmDataMemoryBarrier (); + + MmioWrite32 (PcieBaseAddress + IATU_LWR_BASE_ADDR_OFF_OUTBOUND_0, + (UINT32)(CpuBase & 0xFFFFFFFF)); + MmioWrite32 (PcieBaseAddress + IATU_UPPER_BASE_ADDR_OFF_OUTBOUND_0, + (UINT32)(CpuBase >> 32)); + MmioWrite32 (PcieBaseAddress + IATU_LIMIT_ADDR_OFF_OUTBOUND_0, + (UINT32)(CpuBase + Size - 1)); + MmioWrite32 (PcieBaseAddress + IATU_LWR_TARGET_ADDR_OFF_OUTBOUND_0, + (UINT32)(PciBase & 0xFFFFFFFF)); + MmioWrite32 (PcieBaseAddress + IATU_UPPER_TARGET_ADDR_OFF_OUTBOUND_0, + (UINT32)(PciBase >> 32)); + MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_1_OFF_OUTBOUND_0, + Type); + MmioWrite32 (PcieBaseAddress + IATU_REGION_CTRL_2_OFF_OUTBOUND_0, + IATU_REGION_CTRL_2_OFF_OUTBOUND_0_REGION_EN | EnableFlags); +} + +/** + Perform PCIE slot reset using external GPIO pin. + + @param [in] PcieBaseAddress PCIE controller base address. + + @retval none + +**/ +STATIC +VOID +WaitForLink ( + IN EFI_PHYSICAL_ADDRESS PcieBaseAddress + ) +{ + UINT32 Mask; + UINT32 Status; + UINT32 Timeout; + + if (!(MmioRead32 (PcieBaseAddress + PCIE_PM_STATUS) & PCIE_PM_LTSSM_STAT_MASK)) { + DEBUG ((DEBUG_INIT, "%a: no PCIE device detected\n", __FUNCTION__)); + return; + } + + /* Wait for the link to establish itself */ + DEBUG ((DEBUG_INIT, "%a: waiting for PCIE link\n", __FUNCTION__)); + + Mask = PCIE_GLOBAL_STATUS_RDLH_LINK_UP | PCIE_GLOBAL_STATUS_PHY_LINK_UP; + Timeout = PCIE_LINK_UP_TIMEOUT_US / 10; + do { + Status = MmioRead32 (PcieBaseAddress + PCIE_GLOBAL_STATUS_REG); + if ((Status & Mask) == Mask) { + DEBUG ((DEBUG_ERROR, "pcie@0x%x link UP\n", PcieBaseAddress)); + break; + } + gBS->Stall (10); + } while (Timeout--); +} + +/** + Perform PCIE slot reset using external GPIO pin. + + @param [in] *PcieResetGpio GPIO pin description. + + @retval EFI_SUCEESS PCIE slot reset succeeded. + @retval Other Return error status. + +**/ +STATIC +EFI_STATUS +ResetPcieSlot ( + IN MV_GPIO_PIN *PcieResetGpio + ) +{ + EMBEDDED_GPIO_MODE Mode; + EMBEDDED_GPIO_PIN GpioPin; + EMBEDDED_GPIO *GpioProtocol; + EFI_STATUS Status; + + /* Get GPIO protocol */ + Status = MvGpioGetProtocol (PcieResetGpio->ControllerType, &GpioProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "%a: Unable to find GPIO protocol\n", __FUNCTION__)); + return Status; + } + + GpioPin = GPIO (PcieResetGpio->ControllerId, PcieResetGpio->PinNumber), + + /* Reset the slot by toggling the GPIO pin */ + Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_1 : GPIO_MODE_OUTPUT_0; + Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode); + gBS->Stall (10 * 1000); + + Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1; + Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode); + gBS->Stall (20 * 1000); + + return EFI_SUCCESS; +} + +/** + Obtain resources and perform a low-level PCIE controllers + configuration. + + @param [in] ImageHandle The image handle. + @param [in] *SystemTable The system table. + + @retval EFI_SUCEESS PCIE configuration successful. + @retval Other Return error status. + +**/ +EFI_STATUS +EFIAPI +Armada7k8kPciHostBridgeLibConstructor ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + MARVELL_BOARD_DESC_PROTOCOL *BoardDescriptionProtocol; + MV_BOARD_PCIE_DESCRIPTION *BoardPcieDescription; + MV_PCIE_CONTROLLER *PcieController; + EFI_PHYSICAL_ADDRESS PcieBaseAddress; + EFI_STATUS Status; + UINTN Index; + + /* Obtain list of available controllers */ + Status = gBS->LocateProtocol (&gMarvellBoardDescProtocolGuid, + NULL, + (VOID **)&BoardDescriptionProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: Cannot locate BoardDesc protocol\n", + __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + Status = BoardDescriptionProtocol->PcieDescriptionGet ( + BoardDescriptionProtocol, + &BoardPcieDescription); + if (Status == EFI_NOT_FOUND) { + /* No controllers used on the platform, exit silently */ + return EFI_SUCCESS; + } else if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: Cannot get Pcie board desc from BoardDesc protocol\n", + __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + + for (Index = 0; Index < BoardPcieDescription->PcieControllerCount; Index++) { + + PcieController = &(BoardPcieDescription->PcieControllers[Index]); + + ASSERT (PcieController->PcieBusMin == 0); + ASSERT (PcieController->ConfigSpaceAddress % SIZE_256MB == 0); + + if (PcieController->HaveResetGpio == TRUE) { + /* Reset PCIE slot */ + Status = ResetPcieSlot (&PcieController->PcieResetGpio); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, + "%a: Cannot reset Pcie Slot\n", + __FUNCTION__)); + return EFI_DEVICE_ERROR; + } + } + + /* Low level PCIE controller configuration */ + PcieBaseAddress = PcieController->PcieBaseAddress; + + MmioAndThenOr32 (PcieBaseAddress + PORT_LINK_CTRL_OFF, + ~PORT_LINK_CTRL_OFF_LINK_CAPABLE_MASK, + PORT_LINK_CTRL_OFF_LINK_CAPABLE_x4); + + MmioAndThenOr32 (PcieBaseAddress + GEN2_CTRL_OFF, + ~GEN2_CTRL_OFF_NUM_OF_LANES_MASK, + GEN2_CTRL_OFF_NUM_OF_LANES(4) | GEN2_CTRL_OFF_DIRECT_SPEED_CHANGE); + + MmioAndThenOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET, + ~(PCIE_GLOBAL_CTRL_DEVICE_TYPE_MASK | PCIE_GLOBAL_APP_LTSSM_EN), + PCIE_GLOBAL_CTRL_DEVICE_TYPE_RC); + + MmioWrite32 (PcieBaseAddress + PCIE_ARCACHE_TRC_REG, + ARCACHE_DEFAULT_VALUE); + + MmioWrite32 (PcieBaseAddress + PCIE_AWCACHE_TRC_REG, + AWCACHE_DEFAULT_VALUE); + + MmioAndThenOr32 (PcieBaseAddress + PCIE_ARUSER_REG, + ~AX_USER_DOMAIN_MASK, + AX_USER_DOMAIN_OUTER_SHAREABLE); + + MmioAndThenOr32 (PcieBaseAddress + PCIE_AWUSER_REG, + ~AX_USER_DOMAIN_MASK, + AX_USER_DOMAIN_OUTER_SHAREABLE); + + MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CTL_2, + ~TARGET_LINK_SPEED_MASK, + LINK_SPEED_GEN_3); + + MmioAndThenOr32 (PcieBaseAddress + PCIE_LINK_CAPABILITY, + ~TARGET_LINK_SPEED_MASK, + LINK_SPEED_GEN_3); + + MmioOr32 (PcieBaseAddress + PCIE_GEN3_EQU_CTRL, + GEN3_EQU_EVAL_2MS_DISABLE); + + MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_CTRL_OFFSET, + PCIE_GLOBAL_APP_LTSSM_EN); + + /* Region 0: MMIO32 range */ + ConfigureWindow (PcieBaseAddress, + 0, + PcieController->PcieMmio32WinBase, + PcieController->PcieMmio32WinBase, + PcieController->PcieMmio32WinSize, + IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM, + 0); + + /* Region 1: Type 0 config space */ + ConfigureWindow (PcieBaseAddress, + 1, + PcieController->ConfigSpaceAddress, + 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 (PcieBaseAddress, + 2, + PcieController->ConfigSpaceAddress + SIZE_64KB, + 0x0, + PcieController->PcieBusMax * SIZE_1MB, + 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 (PcieBaseAddress, + 3, + PcieController->PcieIoTranslation, + PcieController->PcieIoWinBase, + PcieController->PcieIoWinSize, + IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_IO, + 0); + + /* Region 4: MMIO64 range */ + ConfigureWindow (PcieBaseAddress, + 4, + PcieController->PcieMmio64WinBase, + PcieController->PcieMmio64WinBase, + PcieController->PcieMmio64WinSize, + IATU_REGION_CTRL_1_OFF_OUTBOUND_0_TYPE_MEM, + 0); + + MmioOr32 (PcieBaseAddress + PCIE_GLOBAL_INT_MASK1_REG, + PCIE_INT_A_ASSERT_MASK | + PCIE_INT_B_ASSERT_MASK | + PCIE_INT_C_ASSERT_MASK | + PCIE_INT_D_ASSERT_MASK); + + WaitForLink (PcieBaseAddress); + + /* Enable the RC */ + MmioOr32 (PcieBaseAddress + PCI_COMMAND_OFFSET, + EFI_PCI_COMMAND_IO_SPACE | + EFI_PCI_COMMAND_MEMORY_SPACE | + EFI_PCI_COMMAND_BUS_MASTER); + } + + return EFI_SUCCESS; +} -- 2.7.4 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#40321): https://edk2.groups.io/g/devel/message/40321 Mute This Topic: https://groups.io/mt/31553480/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-