From c76bf98bc8f988ea2f3953563f94fab8268ec3bd Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Thu, 25 Jan 2018 12:08:56 +0000 Subject: Silicon/Socionext/SynQuacer: implement menu option to set max PCIe speed Add menu options to the SynQuacer Platform menu screen to limit the maximum PCIe link speed for each slot individually. This may be useful to work around potential PCIe issues. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ard Biesheuvel Reviewed-by: Leif Lindholm --- .../Socionext/SynQuacer/Drivers/PlatformDxe/Pci.c | 35 ++++++- .../SynQuacer/Drivers/PlatformDxe/PlatformDxe.c | 107 +++++++++++++++++++++ .../SynQuacer/Drivers/PlatformDxe/PlatformDxe.h | 13 +++ .../SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf | 11 +++ .../Drivers/PlatformDxe/PlatformDxeHii.uni | 29 ++++++ .../Drivers/PlatformDxe/PlatformDxeHii.vfr | 69 +++++++++++++ 6 files changed, 262 insertions(+), 2 deletions(-) create mode 100644 Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.uni create mode 100644 Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.vfr (limited to 'Silicon/Socionext/SynQuacer/Drivers') diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/Pci.c b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/Pci.c index 9af3dd942c..7c69a8051a 100644 --- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/Pci.c +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/Pci.c @@ -45,6 +45,11 @@ RetrainAsm1184eDownstreamPort ( EFI_STATUS Status; PCIE_CAP Cap; PCI_REG_PCIE_LINK_CONTROL LinkControl; + UINTN SegmentNumber; + UINTN BusNumber; + UINTN DeviceNumber; + UINTN FunctionNumber; + UINT8 MaxSpeed; // // The upstream and downstream ports share the same PID/VID, so check @@ -64,8 +69,34 @@ RetrainAsm1184eDownstreamPort ( return; } - DEBUG ((DEBUG_INFO, "%a: retraining ASM118x downstream PCIe port\n", - __FUNCTION__)); + Status = PciIo->GetLocation (PciIo, &SegmentNumber, &BusNumber, &DeviceNumber, + &FunctionNumber); + ASSERT_EFI_ERROR (Status); + + // + // Check whether this downstream port is described by any of our 'slot' + // definitions, and get the maximum speed if this is the case. + // + switch (SYNQUACER_PCI_LOCATION (SegmentNumber, BusNumber, DeviceNumber)) { + case SYNQUACER_PCI_SLOT0_LOCATION: + MaxSpeed = mHiiSettings->PcieSlot0MaxSpeed; + break; + case SYNQUACER_PCI_SLOT1_LOCATION: + MaxSpeed = mHiiSettings->PcieSlot1MaxSpeed; + break; + case SYNQUACER_PCI_SLOT2_LOCATION: + MaxSpeed = mHiiSettings->PcieSlot2MaxSpeed; + break; + default: + MaxSpeed = PCIE_MAX_SPEED_UNLIMITED; + } + if (MaxSpeed == PCIE_MAX_SPEED_GEN1) { + return; + } + + DEBUG ((DEBUG_INFO, + "%a: retraining ASM118x downstream PCIe port at %04x:%02x:%02x to Gen2\n", + __FUNCTION__, SegmentNumber, BusNumber, DeviceNumber)); Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint16, ASM118x_PCIE_LINK_CONTROL_OFFSET, 1, &LinkControl); diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c index 91c1b66ea1..b60607d058 100644 --- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.c @@ -14,6 +14,36 @@ #include "PlatformDxe.h" +UINT64 mHiiSettingsVal; +SYNQUACER_PLATFORM_VARSTORE_DATA *mHiiSettings; + +typedef struct { + VENDOR_DEVICE_PATH VendorDevicePath; + EFI_DEVICE_PATH_PROTOCOL End; +} HII_VENDOR_DEVICE_PATH; + +STATIC HII_VENDOR_DEVICE_PATH mPlatformDxeHiiVendorDevicePath = { + { + { + HARDWARE_DEVICE_PATH, + HW_VENDOR_DP, + { + (UINT8) (sizeof (VENDOR_DEVICE_PATH)), + (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8) + } + }, + SYNQUACER_PLATFORM_FORMSET_GUID + }, + { + END_DEVICE_PATH_TYPE, + END_ENTIRE_DEVICE_PATH_SUBTYPE, + { + (UINT8) (END_DEVICE_PATH_LENGTH), + (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8) + } + } +}; + STATIC EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR mNetsecDesc[] = { { ACPI_ADDRESS_SPACE_DESCRIPTOR, // Desc @@ -144,6 +174,77 @@ SmmuEnableCoherentDma ( SMMU_SCR0_SHCFG_INNER | SMMU_SCR0_MTCFG | SMMU_SCR0_MEMATTR_INNER_OUTER_WB); } +STATIC +EFI_STATUS +InstallHiiPages ( + VOID + ) +{ + EFI_STATUS Status; + EFI_HII_HANDLE HiiHandle; + EFI_HANDLE DriverHandle; + + DriverHandle = NULL; + Status = gBS->InstallMultipleProtocolInterfaces (&DriverHandle, + &gEfiDevicePathProtocolGuid, + &mPlatformDxeHiiVendorDevicePath, + NULL); + if (EFI_ERROR (Status)) { + return Status; + } + + HiiHandle = HiiAddPackages (&gSynQuacerPlatformFormSetGuid, + DriverHandle, + PlatformDxeStrings, + PlatformDxeHiiBin, + NULL); + + if (HiiHandle == NULL) { + gBS->UninstallMultipleProtocolInterfaces (DriverHandle, + &gEfiDevicePathProtocolGuid, + &mPlatformDxeHiiVendorDevicePath, + NULL); + return EFI_OUT_OF_RESOURCES; + } + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EnableSettingsForm ( + VOID + ) +{ + EFI_STATUS Status; + UINTN VarSize; + SYNQUACER_PLATFORM_VARSTORE_DATA Settings; + + VarSize = sizeof (Settings); + Status = gRT->GetVariable (SYNQUACER_PLATFORM_VARIABLE_NAME, + &gSynQuacerPlatformFormSetGuid, NULL, &VarSize, &Settings); + if (Status == EFI_NOT_FOUND) { + // + // Variable does not exist yet - create it + // + SetMem (&Settings, sizeof (Settings), 0); + Status = gRT->SetVariable (SYNQUACER_PLATFORM_VARIABLE_NAME, + &gSynQuacerPlatformFormSetGuid, + EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS, + sizeof (Settings), &Settings); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: EfiSetVariable failed - %r\n", __FUNCTION__, + Status)); + return Status; + } + } else if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_WARN, "%a: EfiGetVariable failed - %r\n", __FUNCTION__, + Status)); + return Status; + } + + return InstallHiiPages (); +} + EFI_STATUS EFIAPI PlatformDxeEntryPoint ( @@ -156,6 +257,9 @@ PlatformDxeEntryPoint ( UINTN DtbSize; EFI_HANDLE Handle; + mHiiSettingsVal = PcdGet64 (PcdPlatformSettings); + mHiiSettings = (SYNQUACER_PLATFORM_VARSTORE_DATA *)&mHiiSettingsVal; + Dtb = NULL; Status = DtPlatformLoadDtb (&Dtb, &DtbSize); if (!EFI_ERROR (Status)) { @@ -197,5 +301,8 @@ PlatformDxeEntryPoint ( Status = RegisterPcieNotifier (); ASSERT_EFI_ERROR (Status); + Status = EnableSettingsForm (); + ASSERT_EFI_ERROR (Status); + return EFI_SUCCESS; } diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.h b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.h index d1dad2a3ea..53898b5828 100644 --- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.h +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.h @@ -16,18 +16,31 @@ #define __PLATFORM_DXE_H__ #include +#include #include #include #include +#include #include +#include #include #include +#include #include #include +#include #include +#include +#include #include #include +extern UINT8 PlatformDxeHiiBin[]; +extern UINT8 PlatformDxeStrings[]; + +extern UINT64 mHiiSettingsVal; +extern SYNQUACER_PLATFORM_VARSTORE_DATA *mHiiSettings; + EFI_STATUS EFIAPI RegisterPcieNotifier ( diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf index f075957d74..de21ba33df 100644 --- a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxe.inf @@ -25,6 +25,8 @@ [Sources] Pci.c PlatformDxe.c + PlatformDxeHii.uni + PlatformDxeHii.vfr [Packages] EmbeddedPkg/EmbeddedPkg.dec @@ -37,18 +39,24 @@ [LibraryClasses] BaseMemoryLib DebugLib + DevicePathLib DtPlatformDtbLoaderLib + HiiLib IoLib MemoryAllocationLib + PcdLib UefiBootServicesTableLib UefiDriverEntryPoint UefiLib + UefiRuntimeServicesTableLib [Guids] + gEfiHiiPlatformSetupFormsetGuid gFdtTableGuid gNetsecNonDiscoverableDeviceGuid gSynQuacerNonDiscoverableI2cMasterGuid gSynQuacerNonDiscoverableRuntimeI2cMasterGuid + gSynQuacerPlatformFormSetGuid [Protocols] gEdkiiNonDiscoverableDeviceProtocolGuid ## PRODUCES @@ -59,5 +67,8 @@ gSynQuacerTokenSpaceGuid.PcdNetsecEepromBase gSynQuacerTokenSpaceGuid.PcdNetsecPhyAddress +[Pcd] + gSynQuacerTokenSpaceGuid.PcdPlatformSettings + [Depex] TRUE diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.uni b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.uni new file mode 100644 index 0000000000..b274d12ed2 --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.uni @@ -0,0 +1,29 @@ +/** @file +* +* Copyright (c) 2017, Linaro, 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. +* +**/ + +#langdef en-US "English" + +#string STR_FORM_SET_TITLE #language en-US "SynQuacer Platform Settings" +#string STR_FORM_SET_TITLE_HELP #language en-US "Press to set platform specific options." + +#string STR_MAIN_FORM_TITLE #language en-US "SynQuacer Platform Settings" +#string STR_NULL_STRING #language en-US "" + +#string STR_PCIE0_MAX_SPEED_PROMPT #language en-US "PCIe x4 slot max speed" +#string STR_PCIE1_MAX_SPEED_PROMPT #language en-US "PCIe x1 slot 1 max speed" +#string STR_PCIE2_MAX_SPEED_PROMPT #language en-US "PCIe x1 slot 2 max speed" +#string STR_PCIE_MAX_SPEED_HELP #language en-US "The maximum speed the PCIe downstream port is allowed to negotiate" + +#string STR_PCIE_MAX_SPEED_UNLIMITED #language en-US "Unlimited" +#string STR_PCIE_MAX_SPEED_GEN1 #language en-US "Gen1 (2.5 GT/s)" diff --git a/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.vfr b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.vfr new file mode 100644 index 0000000000..52f554b61e --- /dev/null +++ b/Silicon/Socionext/SynQuacer/Drivers/PlatformDxe/PlatformDxeHii.vfr @@ -0,0 +1,69 @@ +/** @file +* +* Copyright (c) 2017, Linaro, 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 + +// +// EFI Variable attributes +// +#define EFI_VARIABLE_NON_VOLATILE 0x00000001 +#define EFI_VARIABLE_BOOTSERVICE_ACCESS 0x00000002 +#define EFI_VARIABLE_RUNTIME_ACCESS 0x00000004 +#define EFI_VARIABLE_READ_ONLY 0x00000008 + +formset + guid = SYNQUACER_PLATFORM_FORMSET_GUID, + title = STRING_TOKEN(STR_FORM_SET_TITLE), + help = STRING_TOKEN(STR_FORM_SET_TITLE_HELP), + classguid = EFI_HII_PLATFORM_SETUP_FORMSET_GUID, + + efivarstore SYNQUACER_PLATFORM_VARSTORE_DATA, + attribute = EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE, // EFI variable attributes + name = SynQuacerPlatformSettings, + guid = SYNQUACER_PLATFORM_FORMSET_GUID; + + form formid = 0x1000, + title = STRING_TOKEN(STR_MAIN_FORM_TITLE); + + oneof varid = SynQuacerPlatformSettings.PcieSlot0MaxSpeed, + prompt = STRING_TOKEN(STR_PCIE0_MAX_SPEED_PROMPT), + help = STRING_TOKEN(STR_PCIE_MAX_SPEED_HELP), + flags = NUMERIC_SIZE_1 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_PCIE_MAX_SPEED_UNLIMITED), value = PCIE_MAX_SPEED_UNLIMITED, flags = DEFAULT; + option text = STRING_TOKEN(STR_PCIE_MAX_SPEED_GEN1), value = PCIE_MAX_SPEED_GEN1, flags = 0; + endoneof; + + oneof varid = SynQuacerPlatformSettings.PcieSlot1MaxSpeed, + prompt = STRING_TOKEN(STR_PCIE1_MAX_SPEED_PROMPT), + help = STRING_TOKEN(STR_PCIE_MAX_SPEED_HELP), + flags = NUMERIC_SIZE_1 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_PCIE_MAX_SPEED_UNLIMITED), value = PCIE_MAX_SPEED_UNLIMITED, flags = DEFAULT; + option text = STRING_TOKEN(STR_PCIE_MAX_SPEED_GEN1), value = PCIE_MAX_SPEED_GEN1, flags = 0; + endoneof; + + oneof varid = SynQuacerPlatformSettings.PcieSlot2MaxSpeed, + prompt = STRING_TOKEN(STR_PCIE2_MAX_SPEED_PROMPT), + help = STRING_TOKEN(STR_PCIE_MAX_SPEED_HELP), + flags = NUMERIC_SIZE_1 | INTERACTIVE | RESET_REQUIRED, + option text = STRING_TOKEN(STR_PCIE_MAX_SPEED_UNLIMITED), value = PCIE_MAX_SPEED_UNLIMITED, flags = DEFAULT; + option text = STRING_TOKEN(STR_PCIE_MAX_SPEED_GEN1), value = PCIE_MAX_SPEED_GEN1, flags = 0; + endoneof; + + subtitle text = STRING_TOKEN(STR_NULL_STRING); + + endform; + +endformset; -- cgit v1.2.3