From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: mx.groups.io; dkim=pass header.i=@linaro.org header.s=google header.b=U/PRuJLL; spf=pass (domain: linaro.org, ip: 209.85.166.65, mailfrom: ard.biesheuvel@linaro.org) Received: from mail-io1-f65.google.com (mail-io1-f65.google.com [209.85.166.65]) by groups.io with SMTP; Thu, 16 May 2019 07:14:54 -0700 Received: by mail-io1-f65.google.com with SMTP id a17so2684709iot.8 for ; Thu, 16 May 2019 07:14:54 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=mime-version:references:in-reply-to:from:date:message-id:subject:to :cc; bh=sL2eSdVLHz/1FKFdVeRX9yQrH/3fiIh90uBS4nW6wMA=; b=U/PRuJLLdOCuHRErbucalDRebn2k88Z1X4TZRst5IMXFvej2LU0wZS6eIb84j4nnxK MlGofdeS8TDlSEIDwf9WppXS5jNvqDjj7+AEwib10pgyBwwat67W4Ph6ShFzYM3qw/3u oKUUD31XSml/76rpD+G9TNATR3UNj/itByx9N9irXES9/J3PinDR3gzmHGFVmYuZ16ZO V29tvuzsHzsHxvcZQI9PkzXVXPTCRxQOPmKIw5eRh0cvmDQMaaXaa+IeOg922a/NGcjO gnr6Wzegq+Gq7gXqhBACYiAcogOZm/OPp4EnRLe7YuJwPOzSqswtdmngmyGhS51cQ/4Q gFWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:references:in-reply-to:from:date :message-id:subject:to:cc; bh=sL2eSdVLHz/1FKFdVeRX9yQrH/3fiIh90uBS4nW6wMA=; b=pEUmel4c2/kNh1jHT4vf3QJO4oYVqz8hN0LHAHHMPlPrP9MAzKIc4vT8DGz+0a99Fq XoRtf3eu3/oRg52K+taHBTvPSOGGZzqrSWXtC9cKNrS1KPHlhrfnt8NNAkRBLYeR3DqO 8+hvod4/Zvm1iO+WrE5iAVgp76GDURWdUMnUtObuHaIyHNmGdijuaLKIqA53eKHBA2Ts rYhbtb+GaB28qGdOiWZkS05p0biSEUSO3Duj05GXF9jzbKqegsk5xuOSqW79esbY/T7p yETT1TNHZQDxIei7SIS6LivIEiQH6y321d/QNhsBof7gZlYkKdhnDyzalFr6QVtydNAD 05mA== X-Gm-Message-State: APjAAAW4eS0PRGar4J43x3/Kv9x3+mvrf7bRF75NaJjYJQm6j5L/NNpN NfHW3XBwuSeGYDQrWyV7drUoWlAAaDhyRPjjmJ9vvA== X-Google-Smtp-Source: APXvYqyaKRFLFppi4BGn0migax7W4vIkh8FdVm6r/9ZhnZwC9sJAaRDnZjLZ4plk4tlPEkkf8VIRj2CUqsohgG/G8ew= X-Received: by 2002:a6b:c842:: with SMTP id y63mr13078931iof.60.1558016093634; Thu, 16 May 2019 07:14:53 -0700 (PDT) MIME-Version: 1.0 References: <1557395622-32425-1-git-send-email-mw@semihalf.com> <1557395622-32425-8-git-send-email-mw@semihalf.com> In-Reply-To: <1557395622-32425-8-git-send-email-mw@semihalf.com> From: "Ard Biesheuvel" Date: Thu, 16 May 2019 16:14:42 +0200 Message-ID: Subject: Re: [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib To: Marcin Wojtas Cc: edk2-devel-groups-io , Leif Lindholm , =?UTF-8?B?SmFuIETEhWJyb8Wb?= , Grzegorz Jaszczyk , Kostya Porotchkin , Jici Gao , Rebecca Cran , kettenis@jive.eu Content-Type: text/plain; charset="UTF-8" On Thu, 9 May 2019 at 11:54, Marcin Wojtas wrote: > > 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 > and Jing Hua / > > Contributed-under: TianoCore Contribution Agreement 1.1 > Signed-off-by: Marcin Wojtas > --- > 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.
> +# Copyright (c) 2019 Marvell International Ltd. 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 = 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.
> + Copyright (c) 2019 Marvell International Ltd. 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. > + > +**/ > +#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.
> + Copyright (c) 2019 Marvell International Ltd. 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. > + > +**/ > +#include > + > +#include > +#include > +#include > +#include > +#include > +#include > + > +#include > +#include > +#include > + > +#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; > + IIRC you merged the 32-bit support for these platforms? If so, please look at SynQuacer how to deal with PCIe support on 32-bit, since this will break it otherwise. (TL;DR get rid of the 64-bit MMIO window when building in ARM mode) > + 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); PciHostBridgeDxe now supports MMIO translation so instead of these asserts, you might want to assign the translation fields instead. > + > + 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.
> + Copyright (c) 2019 Marvell International Ltd. 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. > + > +**/ > + > +#include > + > +#include > + > +#include > +#include > +#include > +#include > +#include > + > +#include > + > +#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, If this is the DBI address, please rename the parameter accordingly. Base address means something else for PCIe in EDK2. > + 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); This seems a bit short for a PCIe reset, no? We use 150ms on SynQuacer, just to be squarely on the safe side of the minimum 100ms mandated by the spec (IIRC) > + > + 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 >