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=Y8ncZz6x; spf=pass (domain: linaro.org, ip: 209.85.128.66, mailfrom: leif.lindholm@linaro.org) Received: from mail-wm1-f66.google.com (mail-wm1-f66.google.com [209.85.128.66]) by groups.io with SMTP; Fri, 10 May 2019 08:50:24 -0700 Received: by mail-wm1-f66.google.com with SMTP id f204so2620014wme.0 for ; Fri, 10 May 2019 08:50:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=TGFJ4Xbs2MvZR3/FSBvuMee9BXIjvCB0BfsS8/nb/WA=; b=Y8ncZz6xAqM8i3yd47DV+qlC5suSfj6gaGbGV9C0Ymi7/JidqN+5IRCS+QyUJW9Zbx 6HmKeaok5Jdca2+EkfR5MOTXUi6txVxL7zBEzoKQaOlJrPmzQfaC5ighdUBfIo0C4tcZ 75Pfely6c6qbIv/JMZKA6q7tkOfajqtxwIp5HPLwnuakndeYT1eLz7A0hJ4xaRpz54jU 6RiKZQT0NMHqpQp7xSEjFpFFAmfzq+9mtlUtRnKiL14mLTIaK6kbxEs7Opxm6tmPe/kD 63wxn/wEdCiY14biOI7lfPT0i01WcOfnp39WXmZsk1K/wvc3KCPRfeJdFKYoiw/FKYUP lGqA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=TGFJ4Xbs2MvZR3/FSBvuMee9BXIjvCB0BfsS8/nb/WA=; b=E8yPmCVYi5kJjD95fqSmh2GF880i7+rmtaMOBMetHFysDugCUD38jiEfDB8O3x6HdJ Hf7WhXc0SsPKR6wv5BqSjNRlsw7Il3P4vq0iygcg0nd+aUOuSo6vZaHnTDdq98o0THpG p6DP2a/ksrhvQaDniDIKuVN+Hm+qeBcSlvozCMxoCDUoKF+eB3iCepTf1WYaTqMQLWNz FtTHzDhyJyvqkJOdrbTGYmxPh1HmFsod4z/TU14gjdmH4Fj0aNaBptUh0maBKxSRKpaf hStUfrrtYiKfmJDxAK96bAhEMbFPeATrlp9CZ6fe+EytiRo/Lz044mPu7IeI8OWcPigM D0JA== X-Gm-Message-State: APjAAAWo99jzzDYPc5V8+DZLSMC9PpzGtHbvj6lRq7yPmFR2XMcmqWjr ce3w/0tVM+PG0QSB2Eo+7OlLaQ== X-Google-Smtp-Source: APXvYqynh7LBrlqEjmOtTJjmc2fZo/37MT3/YK7AoN/v2QyIRhu3udGA2mrGFH0q56kPcc+YEuRiVg== X-Received: by 2002:a1c:f702:: with SMTP id v2mr7894836wmh.0.1557503422656; Fri, 10 May 2019 08:50:22 -0700 (PDT) Return-Path: Received: from bivouac.eciton.net (bivouac.eciton.net. [2a00:1098:0:86:1000:23:0:2]) by smtp.gmail.com with ESMTPSA id f3sm10325351wmb.1.2019.05.10.08.50.21 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Fri, 10 May 2019 08:50:21 -0700 (PDT) Date: Fri, 10 May 2019 16:50:20 +0100 From: "Leif Lindholm" To: Marcin Wojtas Cc: devel@edk2.groups.io, ard.biesheuvel@linaro.org, jsd@semihalf.com, jaz@semihalf.com, kostap@marvell.com, Jici.Gao@arm.com, rebecca@bluestop.org, kettenis@jive.eu Subject: Re: [edk2-platforms: PATCH 07/14] Marvell/Armada7k8k: Implement PciHostBridgeLib Message-ID: <20190510155020.ch5xrdyld2cykclo@bivouac.eciton.net> References: <1557395622-32425-1-git-send-email-mw@semihalf.com> <1557395622-32425-8-git-send-email-mw@semihalf.com> MIME-Version: 1.0 In-Reply-To: <1557395622-32425-8-git-send-email-mw@semihalf.com> User-Agent: NeoMutt/20170113 (1.7.2) Content-Type: text/plain; charset=us-ascii Content-Disposition: inline On Thu, May 09, 2019 at 11:53:35AM +0200, 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 ++++++ Since you so helpfully gave me a link to your branch, I can tell that Silicon/Marvell/Armada7k8k/Library/Armada7k8kPciHostBridgeLib/PciHostBridgeLibConstructor.h has incorrect line endings. If you could address for v2, that would be most appreciated. > 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) Drop space after (UINT8), x2. > + } > + }, > + EISA_PNP_ID(0x0A08), // PCI Express Space before (. > + 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; Drop space after "*)". > + > + 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"")); This ternary is quite an effort to parse. I think a temporary variable for the retult of the & operation would improve this substantially. Alternatively, the wrapping and indentation used in Silicon/Socionext/SynQuacer/Library/SynQuacerPciHostBridgeLib/SynQuacerPciHostBridgeLib.c is a lot easier to read. > + } > + } > + /* 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, > + 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); Why this Stall? Do we need a MemoryFence ()? > + } 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); Why this Stall? Do we need a MemoryFence ()? > + > + Mode = PcieResetGpio->ActiveHigh ? GPIO_MODE_OUTPUT_0 : GPIO_MODE_OUTPUT_1; > + Status = GpioProtocol->Set (GpioProtocol, GpioPin, Mode); > + gBS->Stall (20 * 1000); Why this Stall? Do we need a MemoryFence ()? / Leif > + > + 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 >