Browse Source

CoffeelakeSiliconPkg: Add Missing Library

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2408

Added GbeMdiLib implementation and added additional registers
definitions needed by GbeMdilib. This fixes the linker errors seen
during VS2017 builds

Cc: Chasel Chiu <chasel.chiu@intel.com>
Cc: Nate DeSimone <nathaniel.l.desimone@intel.com>

Signed-off-by: Prince Agyeman <prince.agyeman@intel.com>
Reviewed-by: Chasel Chiu <chasel.chiu@intel.com>
Reviewed-by: Nate DeSimone <nathaniel.l.desimone@intel.com>
Prince Agyeman 4 years ago
parent
commit
068c6c48c6

+ 52 - 1
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Include/Library/GbeMdiLib.h

@@ -21,7 +21,7 @@
   - Registers / bits of new devices introduced in a PCH generation will be just named
     as "_PCH_" without [generation_name] inserted.
 
-  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+  Copyright (c) 2019 - 2020 Intel Corporation. All rights reserved. <BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
@@ -29,7 +29,35 @@
 #ifndef _GBE_MDI_LIB_H_
 #define _GBE_MDI_LIB_H_
 
+
+#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
+
+
+//
+// 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
+
 //
+// LAN PHY MDI settings
+//
+#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
@@ -37,8 +65,22 @@
 //
 #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
 //
 
@@ -131,6 +173,7 @@
 
 **/
 VOID
+EFIAPI
 GbeMdiForceMACtoSMB (
   IN      UINT32  GbeBar
   );
@@ -144,6 +187,7 @@ GbeMdiForceMACtoSMB (
   @retval EFI_TIMEOUT
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiWaitReady (
   IN      UINT32  GbeBar
   );
@@ -160,6 +204,7 @@ GbeMdiWaitReady (
   @retval EFI_TIMEOUT
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiAcquireMdio (
   IN      UINT32  GbeBar
   );
@@ -170,6 +215,7 @@ GbeMdiAcquireMdio (
   @param [in]  GbeBar   GbE MMIO space
 **/
 VOID
+EFIAPI
 GbeMdiReleaseMdio (
   IN      UINT32  GbeBar
   );
@@ -186,6 +232,7 @@ GbeMdiReleaseMdio (
   @retval EFI_DEVICE_ERROR  Returned if both attermps of setting page failed
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiSetPage (
   IN      UINT32  GbeBar,
   IN      UINT32  Page
@@ -200,6 +247,7 @@ GbeMdiSetPage (
   @return EFI_STATUS
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiSetRegister (
   IN      UINT32  GbeBar,
   IN      UINT32  Register
@@ -219,6 +267,7 @@ GbeMdiSetRegister (
   @retval EFI_INVALID_PARAMETER  If Phy Address or Register validaton failed
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiRead (
   IN      UINT32  GbeBar,
   IN      UINT32  PhyAddress,
@@ -239,6 +288,7 @@ GbeMdiRead (
   @retval EFI_INVALID_PARAMETER  If Phy Address or Register validaton failed
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiWrite (
   IN      UINT32  GbeBar,
   IN      UINT32  PhyAddress,
@@ -257,6 +307,7 @@ GbeMdiWrite (
   @return EFI_INVALID_PARAMETER When GbeBar is incorrect
 **/
 EFI_STATUS
+EFIAPI
 GbeMdiGetLanPhyRevision (
   IN      UINT32  GbeBar,
   OUT     UINT16  *LanPhyRevision

+ 13 - 1
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Include/Register/PchRegsLan.h

@@ -30,7 +30,7 @@
   - RegisterName:
     Full register name.
 
-  Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+  Copyright (c) 2019 - 2020 Intel Corporation. All rights reserved. <BR>
 
   SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
@@ -49,6 +49,17 @@
 #define R_LAN_CFG_PMCS                0xCC
 #define B_LAN_CFG_PMCS_PS             (BIT1 | BIT0)
 #define V_LAN_CFG_PMCS_PS0            0x00
+#define R_LAN_MEM_CSR_CTRL                    0
+#define B_LAN_MEM_CSR_CTRL_LANPHYPC_OVERRIDE  BIT16
+#define B_LAN_MEM_CSR_CTRL_LANPHYPC_VAL       BIT17
+#define R_LAN_MEM_CSR_CTRL_EXT             0x0018
+#define B_LAN_MEM_CSR_CTRL_EXT_LPCD        BIT2
+#define B_LAN_MEM_CSR_CTRL_EXT_FORCE_SMB   BIT11
+#define R_LAN_MEM_CSR_MDIC                 0x0020
+#define B_LAN_MEM_CSR_MDIC_RB              BIT28
+#define B_LAN_MEM_CSR_MDIC_DATA            0xFFFF
+#define R_LAN_MEM_CSR_EXTCNF_CTRL          0x0F00
+#define B_LAN_MEM_CSR_EXTCNF_CTRL_SWFLAG   BIT5
 #define R_LAN_MEM_CSR_RAL                  0x5400
 #define R_LAN_MEM_CSR_RAH                  0x5404
 #define B_LAN_MEM_CSR_RAH_RAH              0x0000FFFF
@@ -56,3 +67,4 @@
 #define B_LAN_MEM_CSR_WUC_APME             BIT0
 
 #endif
+

+ 391 - 0
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGbeMdiLib/GbeMdiLib.c

@@ -0,0 +1,391 @@
+/** @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) 2020 Intel Corporation. All rights reserved. <BR>
+
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+@par Specification Reference:
+**/
+
+#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/PchRegsLan.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
+EFIAPI
+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
+EFIAPI
+GbeMdiForceMacToSmb (
+  IN      UINT32  GbeBar
+  )
+{
+  MmioOr32 (GbeBar + R_LAN_MEM_CSR_CTRL_EXT, B_LAN_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
+EFIAPI
+GbeMdiWaitReady (
+  IN      UINT32  GbeBar
+  )
+{
+  UINT32  Count;
+
+  for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+    if (MmioRead32 (GbeBar + R_LAN_MEM_CSR_MDIC) & B_LAN_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
+EFIAPI
+GbeMdiAcquireMdio (
+  IN      UINT32  GbeBar
+  )
+{
+  UINT32  ExtCnfCtrl;
+  UINT32  Count;
+
+  MmioOr32 (GbeBar + R_LAN_MEM_CSR_EXTCNF_CTRL, B_LAN_MEM_CSR_EXTCNF_CTRL_SWFLAG);
+  for (Count = 0; Count < GBE_MAX_LOOP_TIME; ++Count) {
+    ExtCnfCtrl = MmioRead32 (GbeBar + R_LAN_MEM_CSR_EXTCNF_CTRL);
+    if (ExtCnfCtrl & B_LAN_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
+EFIAPI
+GbeMdiReleaseMdio (
+  IN      UINT32  GbeBar
+  )
+{
+  ASSERT (MmioRead32 (GbeBar + R_LAN_MEM_CSR_EXTCNF_CTRL) & B_LAN_MEM_CSR_EXTCNF_CTRL_SWFLAG);
+  MmioAnd32 (GbeBar + R_LAN_MEM_CSR_EXTCNF_CTRL, (UINT32) ~B_LAN_MEM_CSR_EXTCNF_CTRL_SWFLAG);
+  ASSERT ((MmioRead32 (GbeBar + R_LAN_MEM_CSR_EXTCNF_CTRL) & B_LAN_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
+EFIAPI
+GbeMdiSetPage (
+  IN      UINT32  GbeBar,
+  IN      UINT32  Page
+  )
+{
+  EFI_STATUS  Status;
+
+  MmioWrite32 (GbeBar + R_LAN_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_LAN_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
+EFIAPI
+GbeMdiSetRegister (
+  IN      UINT32  GbeBar,
+  IN      UINT32  Register
+  )
+{
+  MmioWrite32 (GbeBar + R_LAN_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
+EFIAPI
+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_LAN_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
+EFIAPI
+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_LAN_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_LAN_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
+EFIAPI
+GbeMdiGetLanPhyRevision (
+  IN      UINT32  GbeBar,
+  OUT     UINT16  *LanPhyRevision
+  )
+{
+  EFI_STATUS    Status;
+  UINT8         LpcdLoop;
+
+  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_LAN_MEM_CSR_CTRL) & (B_LAN_MEM_CSR_CTRL_LANPHYPC_OVERRIDE | B_LAN_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_LAN_MEM_CSR_CTRL, B_LAN_MEM_CSR_CTRL_LANPHYPC_OVERRIDE);
+    MmioOr32 (GbeBar + R_LAN_MEM_CSR_CTRL, B_LAN_MEM_CSR_CTRL_LANPHYPC_VAL);
+
+    //
+    // Poll on LPCD for 100mSec
+    //
+    LpcdLoop = 101;
+    while (LpcdLoop > 0) {
+      if (MmioRead32 (GbeBar + R_LAN_MEM_CSR_CTRL_EXT) & B_LAN_MEM_CSR_CTRL_EXT_LPCD) {
+        break;
+      } else {
+        LpcdLoop--;
+        MicroSecondDelay (1000);
+      }
+    }
+
+    if (LpcdLoop > 0) {
+      Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_02, R_PHY_MDI_GENEREAL_REGISTER_03_PHY_IDENTIFIER_2, LanPhyRevision);
+    }
+    //
+    // Restore LANPHYPC
+    // 1. Turn LCD off - 1st cycle.
+    // 2. Remove SW signal override - 2nd cycle.
+    //
+    MmioAnd32 (GbeBar + R_LAN_MEM_CSR_CTRL, (UINT32) ~B_LAN_MEM_CSR_CTRL_LANPHYPC_VAL);
+    MmioAnd32 (GbeBar + R_LAN_MEM_CSR_CTRL, (UINT32) ~B_LAN_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;
+}
+

+ 32 - 0
Silicon/Intel/CoffeelakeSiliconPkg/Pch/Library/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf

@@ -0,0 +1,32 @@
+## @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) 2020 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
+  CoffeelakeSiliconPkg/SiPkg.dec
+
+[Sources]
+  GbeMdiLib.c

+ 1 - 0
Silicon/Intel/CoffeelakeSiliconPkg/Pch/PchInit/Smm/PchInitSmm.inf

@@ -46,6 +46,7 @@ TimerLib
 ConfigBlockLib
 PmcPrivateLib
 SataLib
+GbeMdiLib
 
 [Packages]
 MdePkg/MdePkg.dec

+ 3 - 1
Silicon/Intel/CoffeelakeSiliconPkg/SiPkgCommonLib.dsc

@@ -1,7 +1,7 @@
 ## @file
 #  Component description file for the Coffee Lake silicon package both PEI and DXE libraries DSC file.
 #
-# Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
+# Copyright (c) 2019 - 2020 Intel Corporation. All rights reserved. <BR>
 #
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -34,6 +34,8 @@ DEFINE  PCH = Cnl
  PchPcieRpLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchPcieRpLib/PeiDxeSmmPchPcieRpLib.inf
  PchPcrLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchPcrLib/PeiDxeSmmPchPcrLib.inf
  PmcLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPmcLib/PeiDxeSmmPmcLib.inf
+ GbeMdiLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmGbeMdiLib/PeiDxeSmmGbeMdiLib.inf
+
 
  PchSbiAccessLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmPchSbiAccessLib/PeiDxeSmmPchSbiAccessLib.inf
  GpioLib|$(PLATFORM_SI_PACKAGE)/Pch/Library/PeiDxeSmmGpioLib/PeiDxeSmmGpioLib.inf