REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3171
Adds the following files: * IpBlock/Gbe/IncludePrivate * IpBlock/Gbe/Library * IpBlock/Gbe/LibraryPrivate Cc: Sai Chaganty <rangasai.v.chaga...@intel.com> Cc: Nate DeSimone <nathaniel.l.desim...@intel.com> Signed-off-by: Heng Luo <heng....@intel.com> --- Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h | 324 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c | 121 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf | 43 +++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c | 388 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf | 34 ++++++++++++++++++++++++++++++++++ 6 files changed, 978 insertions(+) diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h new file mode 100644 index 0000000000..b8274ed3dc --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Library/GbeMdiLib.h @@ -0,0 +1,324 @@ +/** @file + Header file for GbeMdiLib. + + Conventions: + + - Prefixes: + Definitions beginning with "R_" are registers + Definitions beginning with "B_" are bits within registers + Definitions beginning with "V_" are meaningful values within the bits + Definitions beginning with "S_" are register sizes + Definitions beginning with "N_" are the bit position + - In general, PCH registers are denoted by "_PCH_" in register names + - Registers / bits that are different between PCH generations are denoted by + "_PCH_[generation_name]_" in register/bit names. + - Registers / bits that are specific to PCH-H denoted by "_H_" in register/bit names. + Registers / bits that are specific to PCH-LP denoted by "_LP_" in register/bit names. + e.g., "_PCH_LP_" + Registers / bits names without or _LP_ apply for LP. + - Registers / bits that are different between SKUs are denoted by "_[SKU_name]" + at the end of the register/bit names + - Registers / bits of new devices introduced in a PCH generation will be just named + as "_PCH_" without [generation_name] inserted. + + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _GBE_MDI_LIB_H_ +#define _GBE_MDI_LIB_H_ + +// +// Maximum loop time for GbE status check +// 4000 * 50 = 200 mSec in total +// +#define GBE_MAX_LOOP_TIME 4000 +#define GBE_ACQUIRE_MDIO_DELAY 50 +#define GBE_MDI_SET_PAGE_DELAY 4000 // 4 mSec delay after setting page + +// +// LAN PHY MDI settings +// +// MDI Control Register Bits +// 31:30 Reserved +// This field is reserved and returns 0. +// 29 Interrupt Enable. +// When this bit is set to 1 by software, it causes the device to assert +// an interrupt indicating the end of an MDI cycle. +// 28 Ready. +// Set to 1 by the device at the end of MDI transaction (i.e., indicates a Read or +// Write has been completed. It should be reset to 0 by software at the same time the +// command is written. +// 27:26 Opcode +// For an MDI write, the opcode equals 01b, and for MDI read, 10b. 00b and +// 11b are reserved and should not be used. +// 25:21 PHYAdd +// PHY Address +// 20:16 RegAdd +// PHY Register Address +// 15:0 Data + +#define B_PHY_MDI_READY BIT28 +#define B_PHY_MDI_READ BIT27 +#define B_PHY_MDI_WRITE BIT26 +// +// PHY SPECIFIC registers +// +#define B_PHY_MDI_PHY_ADDRESS_02 BIT22 +// +// PHY GENERAL registers +// Registers 0 to 15 are defined by the specification +// Registers 16 to 31 are left available to the vendor +// +#define B_PHY_MDI_PHY_ADDRESS_01 BIT21 +#define B_PHY_MDI_PHY_ADDRESS_MASK (BIT25 | BIT24 | BIT23 | BIT22 | BIT21) +// +// PHY Identifier Register 2 +// Bits [15:10] - PHY ID Number - The PHY identifier composed of bits 3 through 18 +// of the Organizationally Unique Identifier (OUI) +// Bits [9:4] - Device Model Number +// Bits [3:0] - Device Revision Number +// +#define R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2 0x00030000 + +#define MDI_REG_SHIFT(x) (x << 16) +#define B_PHY_MDI_PHY_REGISTER_MASK (BIT20 | BIT19 | BIT18 | BIT17 | BIT16) +#define R_PHY_MDI_PHY_REG_SET_ADDRESS 0x00110000 // Used after new page setting +#define R_PHY_MDI_PHY_REG_DATA_READ_WRITE 0x00120000 +#define R_PHY_MDI_PHY_REG_SET_PAGE 0x001F0000 + +// +// LAN PHY MDI registers and bits +// + +// +// Page 769 Port Control Registers +// 6020h (769 * 32) +// +#define PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS 769 +// +// Custom Mode Control PHY Address 01, Page 769, Register 16 +// +#define R_PHY_MDI_PAGE_769_REGISETER_16_CMC 0x0010 +// +// Custom Mode Control +// Page 769, Register 16, BIT 10 +// 0 - normal MDIO frequency access +// 1 - reduced MDIO frequency access (slow mdio) +// required for read during cable disconnect +// +#define B_PHY_MDI_PAGE_769_REGISETER_16_CMC_MDIO_FREQ_ACCESS BIT10 +// +// Port General Configuration PHY Address 01, Page 769, Register 17 +// +#define R_PHY_MDI_PAGE_769_REGISETER_17_PGC 0x0011 +// +// Page 769, Register 17, BIT 4 +// Enables host wake up +// +#define B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP BIT4 +// +// Page 769, Register 17, BIT 2 +// Globally enable the MAC power down feature while the +// GbE supports WoL. When set to 1b, +// pages 800 and 801 are enabled for +// configuration and Host_WU_Active is not blocked for writes. +// +#define B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE BIT2 + +// +// Page 800 Wake Up Registers +// 6400h (800 * 32) +// +#define PHY_MDI_PAGE_800_WAKE_UP_REGISTERS 800 +// +// Wake Up Control - WUC PHY Address 01, Page 800, Register 1 +// 1h (Register 1) +// +#define R_PHY_MDI_PAGE_800_REGISETER_1_WUC 0x0001 +// +// Wake Up Control - (WUC) +// Page 800, Register 1, BIT 0 +// Advance Power Management Enable (APME) +// If set to 1b, APM wake up is enabled. +// +#define B_PHY_MDI_PAGE_800_REGISETER_1_WUC_APME BIT0 +// +// Receive Address Low - RAL PHY Address 01, Page 800, Register 16 +// 10h (Register 16) +// +#define R_PHY_MDI_PAGE_800_REGISETER_16_RAL0 0x0010 +// +// Receive Address Low - RAL PHY Address 01, Page 800, Register 17 +// 11h (Register 17) +// +#define R_PHY_MDI_PAGE_800_REGISETER_17_RAL1 0x0011 +// +// Receive Address High - RAH PHY Address 01, Page 800, Register 18 +// 12h (Register 18) +// +#define R_PHY_MDI_PAGE_800_REGISETER_18_RAH0 0x0012 +// +// Receive Address High - RAH PHY Address 01, Page 800, Register 19 +// 13h (Register 19) +// +#define R_PHY_MDI_PAGE_800_REGISETER_19_RAH1 0x0013 +// +// Setting AV (BIT15 RAH is divided on two registers) +// RAH Register 19, Page 800, BIT 31 +// +// Address valid (AV) +// When this bit is set, the relevant RAL and RAH are valid +// +#define B_PHY_MDI_PAGE_800_REGISETER_19_RAH1_ADDRESS_VALID BIT15 +// +// Page 803 Host WoL Packet +// 6460h (803 * 32) +// +#define PHY_MDI_PAGE_803_HOST_WOL_PACKET 803 +// +// Host WoL Packet Clear - HWPC PHY Address 01, Page 803, Register 66 +// +#define R_PHY_MDI_PAGE_803_REGISETER_66_HWPC 0x0042 + + +/** + Change Extended Device Control Register BIT 11 to 1 which + forces the interface between the MAC and the Phy to be on SMBus. + Cleared on the assertion of PCI reset. + + @param [in] GbeBar GbE MMIO space + +**/ +VOID +GbeMdiForceMACtoSMB ( + IN UINT32 GbeBar + ); + +/** + Test for MDIO operation complete. + + @param [in] GbeBar GbE MMIO space + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT +**/ +EFI_STATUS +GbeMdiWaitReady ( + IN UINT32 GbeBar + ); + +/** + Acquire MDIO software semaphore. + + 1. Ensure that MBARA offset F00h [5] = 1b + 2. Poll MBARA offset F00h [5] up to 200ms + + @param [in] GbeBar GbE MMIO space + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT +**/ +EFI_STATUS +GbeMdiAcquireMdio ( + IN UINT32 GbeBar + ); + +/** + Release MDIO software semaphore by clearing MBARA offset F00h [5] + + @param [in] GbeBar GbE MMIO space +**/ +VOID +GbeMdiReleaseMdio ( + IN UINT32 GbeBar + ); + +/** + Sets page on MDI + Page setting is attempted twice. + If first attempt failes MAC and the Phy are force to be on SMBus + + @param [in] GbeBar GbE MMIO space + @param [in] Data Value to write in lower 16bits. + + @retval EFI_SUCCESS Page setting was successfull + @retval EFI_DEVICE_ERROR Returned if both attermps of setting page failed +**/ +EFI_STATUS +GbeMdiSetPage ( + IN UINT32 GbeBar, + IN UINT32 Page + ); + +/** + Sets Register in current page. + + @param [in] GbeBar GbE MMIO space + @param [in] register Register number + + @return EFI_STATUS +**/ +EFI_STATUS +GbeMdiSetRegister ( + IN UINT32 GbeBar, + IN UINT32 Register + ); + + +/** + Perform MDI read. + + @param [in] GbeBar GbE MMIO space + @param [in] PhyAddress Phy Address General - 02 or Specific - 01 + @param [in] PhyRegister Phy Register + @param [out] ReadData Return Value + + @retval EFI_SUCCESS Based on response from GbeMdiWaitReady + @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady + @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed +**/ +EFI_STATUS +GbeMdiRead ( + IN UINT32 GbeBar, + IN UINT32 PhyAddress, + IN UINT32 PhyRegister, + OUT UINT16 *ReadData + ); + +/** + Perform MDI write. + + @param [in] GbeBar GbE MMIO space + @param [in] PhyAddress Phy Address General - 02 or Specific - 01 + @param [in] PhyRegister Phy Register + @param [in] WriteData Value to write in lower 16bits. + + @retval EFI_SUCCESS Based on response from GbeMdiWaitReady + @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady + @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed +**/ +EFI_STATUS +GbeMdiWrite ( + IN UINT32 GbeBar, + IN UINT32 PhyAddress, + IN UINT32 PhyRegister, + IN UINT32 WriteData + ); + +/** + Gets Phy Revision and Model Number + from PHY IDENTIFIER register 2 (offset 3) + + @param [in] GbeBar GbE MMIO space + @param [out] LanPhyRevision Return Value + + @return EFI_STATUS + @return EFI_INVALID_PARAMETER When GbeBar is incorrect +**/ +EFI_STATUS +GbeMdiGetLanPhyRevision ( + IN UINT32 GbeBar, + OUT UINT16 *LanPhyRevision + ); + +#endif // _GBE_MDI_LIB_H_ diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h new file mode 100644 index 0000000000..307f1e159e --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/IncludePrivate/Register/GbeRegs.h @@ -0,0 +1,68 @@ +/** @file + Register names for GbE device + + Conventions: + + - Register definition format: + Prefix_[GenerationName]_[ComponentName]_SubsystemName_RegisterSpace_RegisterName + - Prefix: + Definitions beginning with "R_" are registers + Definitions beginning with "B_" are bits within registers + Definitions beginning with "V_" are meaningful values within the bits + Definitions beginning with "S_" are register size + Definitions beginning with "N_" are the bit position + - [GenerationName]: + Three letter acronym of the generation is used (e.g. SKL,KBL,CNL etc.). + Register name without GenerationName applies to all generations. + - [ComponentName]: + This field indicates the component name that the register belongs to (e.g. PCH, SA etc.) + Register name without ComponentName applies to all components. + Register that is specific to -LP denoted by "_PCH_LP_" in component name. + - SubsystemName: + This field indicates the subsystem name of the component that the register belongs to + (e.g. PCIE, USB, SATA, GPIO, PMC etc.). + - RegisterSpace: + MEM - MMIO space register of subsystem. + IO - IO space register of subsystem. + PCR - Private configuration register of subsystem. + CFG - PCI configuration space register of subsystem. + - RegisterName: + Full register name. + + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ +#ifndef _GBE_REGS_H_ +#define _GBE_REGS_H_ + +#define R_GBE_CFG_MBARA 0x10 +#define N_GBE_CFG_MBARA_ALIGN 17 +#define R_GBE_CFG_PMCS 0xCC +#define B_GBE_CFG_PMCS_PS (BIT1 | BIT0) +#define V_GBE_CFG_PMCS_PS0 0x00 +// +// Gigabit Ethernet LAN Capabilities and Status Registers (Memory space) +// +#define R_GBE_MEM_CSR_CTRL 0 +// +// LANPHYPC: +// Connects to the LCD DEVICE_OFF# signal in the +// LAN Connected Device +// +#define B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE BIT16 // When set to 1 SW driver has the ability to control the LANPHYPC pin value. +#define B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL BIT17 // When set to 1 this bit will define the value of the LANPHYPC pin. +#define R_GBE_MEM_CSR_CTRL_EXT 0x0018 +#define B_GBE_MEM_CSR_CTRL_EXT_LPCD BIT2 //LCD Power Cycle Done (LPCD). This bit indicates whether LCD power cycle is done + //- the bit is set 50/100mSec after LANPHYPC pin assertion. +#define B_GBE_MEM_CSR_CTRL_EXT_FORCE_SMB BIT11 +#define R_GBE_MEM_CSR_MDIC 0x0020 +#define B_GBE_MEM_CSR_MDIC_RB BIT28 +#define R_GBE_MEM_CSR_EXTCNF_CTRL 0x0F00 +#define B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG BIT5 +#define R_GBE_MEM_CSR_RAL 0x5400 +#define R_GBE_MEM_CSR_RAH 0x5404 +#define B_GBE_MEM_CSR_RAH_RAH 0x0000FFFF +#define R_GBE_MEM_CSR_WUC 0x5800 +#define B_GBE_MEM_CSR_WUC_APME BIT0 + +#endif diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c new file mode 100644 index 0000000000..3b51b9eb62 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/GbeLib.c @@ -0,0 +1,121 @@ +/** @file + Gbe Library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <Base.h> +#include <Uefi/UefiBaseType.h> +#include <Library/IoLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseLib.h> +#include <Library/PciSegmentLib.h> +#include <Library/PchInfoLib.h> +#include <Library/PchPcrLib.h> +#include <Library/PchCycleDecodingLib.h> +#include <Library/PmcPrivateLib.h> +#include <Library/SpiAccessLib.h> +#include <Library/GbeMdiLib.h> +#include <IndustryStandard/Pci30.h> +#include <Register/PchRegs.h> +#include <Register/GbeRegs.h> +#include <Library/PchPciBdfLib.h> + +/** + Check whether GbE region is valid + Check SPI region directly since GbE might be disabled in SW. + + @retval TRUE Gbe Region is valid + @retval FALSE Gbe Region is invalid +**/ +BOOLEAN +IsGbeRegionValid ( + VOID + ) +{ + return SpiIsGbeRegionValid (); +} + +/** + Check whether GBE controller is enabled in the platform. + + @retval TRUE GbE is enabled + @retval FALSE GbE is disabled +**/ +BOOLEAN +IsGbePresent ( + VOID + ) +{ + // + // Check PCH Support + // + if (!PchIsGbeSupported ()) { + return FALSE; + } + // + // Check PMC strap/fuse + // + if (!PmcIsGbeSupported ()) { + return FALSE; + } + // + // Check GbE NVM + // + if (IsGbeRegionValid () == FALSE) { + return FALSE; + } + return TRUE; +} + +/** + Verifies Gigabit Ethernet PCI Class Code + + @param [in] GbePciCfgBase GbE PCI Config Space Address + + @retval TRUE GbE Class Code match + @retval FALSE GbE Class Code does not match +**/ +BOOLEAN +STATIC +GbeCheckClassCode ( + UINT64 GbePciCfgBase + ) +{ + UINT8 BaseCode; + UINT8 SubClassCode; + + SubClassCode = PciSegmentRead8 (GbePciCfgBase + PCI_CLASSCODE_OFFSET + 1); + BaseCode = PciSegmentRead8 (GbePciCfgBase + PCI_CLASSCODE_OFFSET + 2); + + if ((BaseCode != PCI_CLASS_NETWORK) || (SubClassCode != PCI_CLASS_NETWORK_ETHERNET)) { + DEBUG ((DEBUG_ERROR, "GbeCheckClassCode : BaseCode(0x%x) or ClassCode(0x%x) is not supported\n", BaseCode, SubClassCode)); + ASSERT (FALSE); + return FALSE; + } + return TRUE; +} + +/** + Checks if Gbe is Enabled or Disabled + + @retval BOOLEAN TRUE if device is enabled, FALSE otherwise. +**/ +BOOLEAN +IsGbeEnabled ( + VOID + ) +{ + UINT64 GbePciBase; + + GbePciBase = GbePciCfgBase (); + + if (PciSegmentRead32 (GbePciBase) != 0xFFFFFFFF) { + return GbeCheckClassCode (GbePciBase); + } + + return FALSE; +} diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf new file mode 100644 index 0000000000..4fef1288af --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/Library/PeiDxeSmmGbeLib/PeiDxeSmmGbeLib.inf @@ -0,0 +1,43 @@ +## @file +# Gbe Library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] +INF_VERSION = 0x00010017 +BASE_NAME = PeiDxeSmmGbeLib +FILE_GUID = FC022ED0-6EB3-43E1-A740-0BA27CBBD010 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = GbeLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +PciSegmentLib +PchInfoLib +PchPcrLib +PchCycleDecodingLib +PmcPrivateLib +SpiAccessLib +GbeMdiLib +PchPciBdfLib + + +[Packages] +MdePkg/MdePkg.dec +TigerlakeSiliconPkg/SiPkg.dec + + +[Sources] +GbeLib.c + diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c new file mode 100644 index 0000000000..7917474406 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/GbeMdiLib.c @@ -0,0 +1,388 @@ +/** @file + Gbe MDI Library. + All function in this library is available for PEI, DXE, and SMM, + But do not support UEFI RUNTIME environment call. + + Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent +**/ + +#include <Base.h> +#include <Uefi/UefiBaseType.h> +#include <Library/TimerLib.h> +#include <Library/IoLib.h> +#include <Library/DebugLib.h> +#include <Library/BaseLib.h> +#include <Library/GbeMdiLib.h> +#include <Register/GbeRegs.h> + + +/** + Validates both Phy Address and Regster. + + @param [in] PhyAddress + @param [in] PhyRegister + + @retval BOOLEAN TRUE Validation passed + FALSE If the data is not within its range + +**/ +BOOLEAN +IsPhyAddressRegisterValid ( + IN UINT32 PhyAddress, + IN UINT32 PhyRegister + ) +{ + if (((PhyAddress & (~B_PHY_MDI_PHY_ADDRESS_MASK)) != 0) || ((PhyRegister & (~B_PHY_MDI_PHY_REGISTER_MASK)) != 0)) { + DEBUG ((DEBUG_ERROR, "IsPhyAddressRegisterValid validation failed! PhyAddress: 0x%08X PhyRegister: 0x%08X \n", PhyAddress, PhyRegister)); + return FALSE; + } + return TRUE; +} + +/** + Change Extended Device Control Register BIT 11 to 1 which + forces the interface between the MAC and the Phy to be on SMBus. + Cleared on the assertion of PCI reset. + + @param [in] GbeBar GbE MMIO space + +**/ +VOID +GbeMdiForceMacToSmb ( + IN UINT32 GbeBar + ) +{ + MmioOr32 (GbeBar + R_GBE_MEM_CSR_CTRL_EXT, B_GBE_MEM_CSR_CTRL_EXT_FORCE_SMB); +} + +/** + Test for MDIO operation complete. + + @param [in] GbeBar GbE MMIO space + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT +**/ +EFI_STATUS +GbeMdiWaitReady ( + IN UINT32 GbeBar + ) +{ + UINT32 Count; + + for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) { + if (MmioRead32 (GbeBar + R_GBE_MEM_CSR_MDIC) & B_GBE_MEM_CSR_MDIC_RB) { + return EFI_SUCCESS; + } + MicroSecondDelay (GBE_ACQUIRE_MDIO_DELAY); + } + DEBUG ((DEBUG_ERROR, "GbeMdiWaitReady Timeout reached. MDIO operation failed to complete in %d micro seconds\n", GBE_MAX_LOOP_TIME * GBE_ACQUIRE_MDIO_DELAY)); + return EFI_TIMEOUT; +} + +/** + Acquire MDIO software semaphore. + + 1. Ensure that MBARA offset F00h [5] = 1b + 2. Poll MBARA offset F00h [5] up to 200ms + + @param [in] GbeBar GbE MMIO space + + @retval EFI_SUCCESS + @retval EFI_TIMEOUT +**/ +EFI_STATUS +GbeMdiAcquireMdio ( + IN UINT32 GbeBar + ) +{ + UINT32 ExtCnfCtrl; + UINT32 Count; + + MmioOr32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL, B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG); + for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) { + ExtCnfCtrl = MmioRead32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL); + if (ExtCnfCtrl & B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG) { + return EFI_SUCCESS; + } + MicroSecondDelay (GBE_ACQUIRE_MDIO_DELAY); + } + DEBUG ((DEBUG_ERROR, "GbeMdiAcquireMdio Timeout. Unable to acquire MDIO Semaphore in %d micro seconds\n", GBE_MAX_LOOP_TIME * GBE_ACQUIRE_MDIO_DELAY)); + return EFI_TIMEOUT; +} + +/** + Release MDIO software semaphore by clearing MBARA offset F00h [5] + + @param [in] GbeBar GbE MMIO space +**/ +VOID +GbeMdiReleaseMdio ( + IN UINT32 GbeBar + ) +{ + ASSERT (MmioRead32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL) & B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG); + MmioAnd32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL, (UINT32) ~B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG); + ASSERT ((MmioRead32 (GbeBar + R_GBE_MEM_CSR_EXTCNF_CTRL) & B_GBE_MEM_CSR_EXTCNF_CTRL_SWFLAG) == 0); +} + +/** + Sets page on MDI + Page setting is attempted twice. + If first attempt failes MAC and the Phy are force to be on SMBus. + + Waits 4 mSec after page setting + + @param [in] GbeBar GbE MMIO space + @param [in] Data Value to write in lower 16bits. + + @retval EFI_SUCCESS Page setting was successfull + @retval EFI_DEVICE_ERROR Returned if both attermps of setting page failed +**/ +EFI_STATUS +GbeMdiSetPage ( + IN UINT32 GbeBar, + IN UINT32 Page + ) +{ + EFI_STATUS Status; + + MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | B_PHY_MDI_PHY_ADDRESS_01 | R_PHY_MDI_PHY_REG_SET_PAGE | ((Page * 32) & 0xFFFF))); + + Status = GbeMdiWaitReady (GbeBar); + + if (Status == EFI_TIMEOUT) { + DEBUG ((DEBUG_INFO, "GbeMdiSetPage Timeout reached. Forcing the interface between the MAC and the Phy to be on SMBus\n")); + GbeMdiForceMacToSmb (GbeBar); + // + // Retry page setting + // + MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | B_PHY_MDI_PHY_ADDRESS_01 | R_PHY_MDI_PHY_REG_SET_PAGE | ((Page * 32) & 0xFFFF))); + Status = GbeMdiWaitReady (GbeBar); + if (Status == EFI_TIMEOUT) { + DEBUG ((DEBUG_ERROR, "GbeMdiSetPage retry page setting failed!\n")); + return EFI_DEVICE_ERROR; + } + } + + // + // Delay required for page to set properly + // + MicroSecondDelay (GBE_MDI_SET_PAGE_DELAY); + + return Status; +} + +/** + Sets Register in current page. + + @param [in] GbeBar GbE MMIO space + @param [in] register Register number valid only in lower 16 Bits + + @return EFI_STATUS +**/ +EFI_STATUS +GbeMdiSetRegister ( + IN UINT32 GbeBar, + IN UINT32 Register + ) +{ + MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | B_PHY_MDI_PHY_ADDRESS_01 | R_PHY_MDI_PHY_REG_SET_ADDRESS | (Register & 0xFFFF))); + return GbeMdiWaitReady (GbeBar); +} + +/** + Perform MDI write. + + @param [in] GbeBar GbE MMIO space + @param [in] PhyAddress Phy Address General - 02 or Specific - 01 + @param [in] PhyRegister Phy Register + @param [in] WriteData Value to write in lower 16bits. + + @retval EFI_SUCCESS Based on response from GbeMdiWaitReady + @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady + @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed +**/ +EFI_STATUS +GbeMdiWrite ( + IN UINT32 GbeBar, + IN UINT32 PhyAddress, + IN UINT32 PhyRegister, + IN UINT32 WriteData + ) +{ + if(!IsPhyAddressRegisterValid (PhyAddress, PhyRegister)) { + DEBUG ((DEBUG_ERROR, "GbeMdiWrite PhyAddressRegister validaton failed!\n")); + return EFI_INVALID_PARAMETER; + } + + MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_WRITE | PhyAddress | PhyRegister | (WriteData & 0xFFFF))); + return GbeMdiWaitReady (GbeBar); +} + +/** + Perform MDI read. + + @param [in] GbeBar GbE MMIO space + @param [in] PhyAddress Phy Address General - 02 or Specific - 01 + @param [in] PhyRegister Phy Register + @param [out] ReadData Return Value + + @retval EFI_SUCCESS Based on response from GbeMdiWaitReady + @retval EFI_TIMEOUT Based on response from GbeMdiWaitReady + @retval EFI_INVALID_PARAMETER If Phy Address or Register validaton failed +**/ +EFI_STATUS +GbeMdiRead ( + IN UINT32 GbeBar, + IN UINT32 PhyAddress, + IN UINT32 PhyRegister, + OUT UINT16 *ReadData + ) +{ + EFI_STATUS Status; + + if(!IsPhyAddressRegisterValid (PhyAddress, PhyRegister)) { + DEBUG ((DEBUG_ERROR, "GbeMdiRead PhyAddressRegister validaton failed!\n")); + return EFI_INVALID_PARAMETER; + } + + MmioWrite32 (GbeBar + R_GBE_MEM_CSR_MDIC, (~B_PHY_MDI_READY) & (B_PHY_MDI_READ | PhyAddress | PhyRegister)); + Status = GbeMdiWaitReady (GbeBar); + if (EFI_SUCCESS == Status) { + *ReadData = (UINT16) MmioRead32 (GbeBar + R_GBE_MEM_CSR_MDIC); + } + return Status; +} + +/** + Gets Phy Revision and Model Number + from PHY IDENTIFIER register 2 (offset 3) + + @param [in] GbeBar GbE MMIO space + @param [out] LanPhyRevision Return Value + + @return EFI_STATUS + @return EFI_INVALID_PARAMETER When GbeBar is incorrect + When Phy register or address is out of bounds +**/ +EFI_STATUS +GbeMdiGetLanPhyRevision ( + IN UINT32 GbeBar, + OUT UINT16 *LanPhyRevision + ) +{ + EFI_STATUS Status; + UINT8 LpcdLoop; + UINT8 Delay; + + if (!((GbeBar & 0xFFFFF000) > 0)) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision GbeBar validation failed! Bar: 0x%08X \n", GbeBar)); + return EFI_INVALID_PARAMETER; + } + + Status = GbeMdiAcquireMdio (GbeBar); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to aquire MDIO semaphore. Status: %r\n", Status)); + return Status; + } + + Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to Set Page 769. Status: %r\n", Status)); + GbeMdiReleaseMdio (GbeBar); + return Status; + } + + // + // Set register to: Custom Mode Control + // Reduced MDIO frequency access (slow mdio) + // BIT 10 set to 1 + // + Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_16_CMC), BIT13 | B_PHY_MDI_PAGE_769_REGISETER_16_CMC_MDIO_FREQ_ACCESS | BIT8 | BIT7); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to enable slow MDIO mode. Status: %r\n", Status)); + GbeMdiReleaseMdio (GbeBar); + return Status; + } + + // + // Read register PHY Version from PHY IDENTIFIER 2 (offset 0x3) + // Bits [9:4] - Device Model Number + // Bits [3:0] - Device Revision Number + // + Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision); + + // + // Failed to obtain PHY REV + // + if (*LanPhyRevision == 0x0) { + if ((MmioRead32 (GbeBar + R_GBE_MEM_CSR_CTRL) & (B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE | B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL))) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to read Phy Revision. Other component tried to initialize GbE and failed.\n")); + Status = EFI_DEVICE_ERROR; + goto phy_exit; + } + DEBUG ((DEBUG_INFO, "GbeMdiGetLanPhyRevision failed to read Revision. Overriding LANPHYPC\n", Status)); + // + // Taking over LANPHYPC + // 1. SW signal override - 1st cycle. + // 2. Turn LCD on - 2nd cycle. + // + MmioOr32 (GbeBar + R_GBE_MEM_CSR_CTRL, B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE); + MmioOr32 (GbeBar + R_GBE_MEM_CSR_CTRL, B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL); + + // + // Poll on LPCD for 100mSec + // + LpcdLoop = 101; + while (LpcdLoop > 0) { + if (MmioRead32 (GbeBar + R_GBE_MEM_CSR_CTRL_EXT) & B_GBE_MEM_CSR_CTRL_EXT_LPCD) { + break; + } else { + LpcdLoop--; + MicroSecondDelay (1000); + } + } + + if (LpcdLoop > 0) { + Delay = 100; + Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision); + while (*LanPhyRevision == 0 && Delay > 0) { + Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision); + if (EFI_ERROR(Status)) { + break; + } + MicroSecondDelay (1000); + Delay --; + } + } + // + // Restore LANPHYPC + // 1. Turn LCD off - 1st cycle. + // 2. Remove SW signal override - 2nd cycle. + // + MmioAnd32 (GbeBar + R_GBE_MEM_CSR_CTRL, (UINT32) ~B_GBE_MEM_CSR_CTRL_LANPHYPC_VAL); + MmioAnd32 (GbeBar + R_GBE_MEM_CSR_CTRL, (UINT32) ~B_GBE_MEM_CSR_CTRL_LANPHYPC_OVERRIDE); + } + +phy_exit: + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to read Revision and Model Number from PHY Identifier 2. Status: %r\n", Status)); + GbeMdiReleaseMdio (GbeBar); + return Status; + } + + // + // Switch back to normal MDIO frequency access + // + Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_16_CMC), (~B_PHY_MDI_PAGE_769_REGISETER_16_CMC_MDIO_FREQ_ACCESS) & (BIT13 | BIT8 | BIT7)); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "GbeMdiGetLanPhyRevision failed to disable slow MDIO mode. Status: %r\n", Status)); + } + + GbeMdiReleaseMdio (GbeBar); + + return Status; +} + diff --git a/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf new file mode 100644 index 0000000000..99a01177f6 --- /dev/null +++ b/Silicon/Intel/TigerlakeSiliconPkg/IpBlock/Gbe/LibraryPrivate/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf @@ -0,0 +1,34 @@ +## @file +# Gbe MDI Library. +# +# All function in this library is available for PEI, DXE, and SMM, +# But do not support UEFI RUNTIME environment call. +# +# Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + + +[Defines] +INF_VERSION = 0x00010017 +BASE_NAME = PeiDxeSmmGbeMdiLib +FILE_GUID = 0360E6F6-892A-4852-BF98-15C0D30D8A48 +VERSION_STRING = 1.0 +MODULE_TYPE = BASE +LIBRARY_CLASS = GbeMdiLib + + +[LibraryClasses] +BaseLib +IoLib +DebugLib +TimerLib + +[Packages] +MdePkg/MdePkg.dec +TigerlakeSiliconPkg/SiPkg.dec + + +[Sources] +GbeMdiLib.c -- 2.24.0.windows.2 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#70966): https://edk2.groups.io/g/devel/message/70966 Mute This Topic: https://groups.io/mt/80274128/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-