123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298 |
- /** @file
- PCH LAN Sx handler implementation.
- Copyright (c) 2019 Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include <Library/TimerLib.h>
- #include "PchInitSmm.h"
- #include <Private/Library/PmcPrivateLib.h>
- #include <Library/GbeMdiLib.h>
- #include <Register/PchRegs.h>
- #include <Register/PchRegsLan.h>
- /**
- Checks if Lan is Enabled or Disabled
- @retval BOOLEAN TRUE if device is enabled, FALSE otherwise.
- **/
- BOOLEAN
- IsGbeEnabled (
- VOID
- )
- {
- UINT64 GbePciBase;
- GbePciBase = PCI_SEGMENT_LIB_ADDRESS (
- DEFAULT_PCI_SEGMENT_NUMBER_PCH,
- DEFAULT_PCI_BUS_NUMBER_PCH,
- PCI_DEVICE_NUMBER_PCH_LAN,
- PCI_FUNCTION_NUMBER_PCH_LAN,
- 0
- );
- if (PciSegmentRead32 (GbePciBase) != 0xFFFFFFFF) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- Configure WOL during Sx entry.
- @param [in] GbeBar GbE MMIO space
- **/
- VOID
- GbeWolWorkaround (
- IN UINT32 GbeBar
- )
- {
- UINT32 RAL0;
- UINT32 RAH0;
- UINT16 WUC;
- EFI_STATUS Status;
- UINT16 Data16;
- //
- // 1. Set page to 769 Port Control Registers
- // 2. Wait 4 mSec
- //
- Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
- if (EFI_ERROR (Status)) return;
- //
- // 3. Set registry to 17 Port General Configuration
- // 4. Copy all settings from Port General Configuration
- //
- Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), &Data16);
- if (EFI_ERROR (Status)) return;
- //
- // 5. Modify BIT 4 and BIT 2 to disable host wake up and set MACPD
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), (Data16 | B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE) & (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP));
- if (EFI_ERROR (Status)) return;
- //
- // 6. Read Receive Address Low and Receive Address High from MMIO
- //
- RAL0 = MmioRead32 (GbeBar + R_LAN_MEM_CSR_RAL);
- RAH0 = MmioRead32 (GbeBar + R_LAN_MEM_CSR_RAH);
- //
- // 7. Set page to 800 Wake Up Registers
- // 8. Wait 4 mSec
- //
- Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_800_WAKE_UP_REGISTERS);
- if (EFI_ERROR (Status)) return;
- //
- // 9. Set registry to 16 Receive Address Low 1/2
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_16_RAL0);
- if (EFI_ERROR (Status)) return;
- //
- // 10. Program first 16 bits [0:15] out of 48 in Receive Address Low 1/2
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAL0 & 0xFFFF));
- if (EFI_ERROR (Status)) return;
- //
- // 11. Set registry to 17 Receive Address Low 2/2
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_17_RAL1);
- if (EFI_ERROR (Status)) return;
- //
- // 12. Program second 16 bits [16:31] out of 48 in Receive Address Low 2/2
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAL0 >> 16));
- if (EFI_ERROR (Status)) return;
- //
- // 13. Set registry to 18 Receive Address High 1/2
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_18_RAH0);
- if (EFI_ERROR (Status)) return;
- //
- // 14. Program last 16 bits [32:47] out of 48
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (RAH0 & B_LAN_MEM_CSR_RAH_RAH));
- if (EFI_ERROR (Status)) return;
- //
- // 15. Set registry to 19 Receive Address High 2/2
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_19_RAH1);
- if (EFI_ERROR (Status)) return;
- //
- // 16. Set Address Valid
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, B_PHY_MDI_PAGE_800_REGISETER_19_RAH1_ADDRESS_VALID);
- if (EFI_ERROR (Status)) return;
- //
- // 17. Set Wake Up Control Register 1
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_800_REGISETER_1_WUC);
- if (EFI_ERROR (Status)) return;
- //
- // 18. Copy WakeUp Control from MAC MMIO
- //
- WUC = (UINT16) MmioRead32 (GbeBar + R_LAN_MEM_CSR_WUC);
- //
- // 19. Store WakeUp Contorl into LCD
- // Modify APME bit to enable APM wake up
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, (WUC & 0xFFFF));
- if (EFI_ERROR (Status)) return;
- //
- // 20. Set page to 803 Host Wol Packet
- // 21. Wait 4 mSec
- //
- Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_803_HOST_WOL_PACKET);
- if (EFI_ERROR (Status)) return;
- //
- // 22. Set registry to 66 Host WoL Packet Clear
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_803_REGISETER_66_HWPC);
- if (EFI_ERROR (Status)) return;
- //
- // 23. Clear WOL Packet
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, R_PHY_MDI_PHY_REG_DATA_READ_WRITE, 0);
- if (EFI_ERROR (Status)) return;
- //
- // 24. Set page to 769 Port Control Registers
- // 25. Wait 4 mSec
- //
- Status = GbeMdiSetPage (GbeBar, PHY_MDI_PAGE_769_PORT_CONTROL_REGISTERS);
- if (EFI_ERROR (Status)) return;
- //
- // 26. Set registry to 17 Port General Configuration
- //
- Status = GbeMdiSetRegister (GbeBar, R_PHY_MDI_PAGE_769_REGISETER_17_PGC);
- if (EFI_ERROR (Status)) return;
- //
- // 27. Copy all settings from Port General Configuration
- //
- Status = GbeMdiRead (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), &Data16);
- if (EFI_ERROR (Status)) return;
- //
- // 28. Modify BIT 4 and BIT 2 to enable host wake up and clear MACPD
- //
- Status = GbeMdiWrite (GbeBar, B_PHY_MDI_PHY_ADDRESS_01, MDI_REG_SHIFT (R_PHY_MDI_PAGE_769_REGISETER_17_PGC), (Data16 | B_PHY_MDI_PAGE_769_REGISETER_17_PGC_HOST_WAKE_UP) & (~B_PHY_MDI_PAGE_769_REGISETER_17_PGC_MACPD_ENABLE));
- if (EFI_ERROR (Status)) return;
- }
- /**
- Additional Internal GbE Controller special cases WOL Support.
- System BIOS is required perform additional steps upon S0 to S3,4,5 transition
- when ME is off and GbE device in D0. This is needed to enable LAN wake
- in particular when platform is shut-down from EFI.
- **/
- VOID
- GbeSxWorkaround (
- VOID
- )
- {
- UINT64 LanRegBase;
- UINT32 GbeBar;
- EFI_STATUS Status;
- LanRegBase = PCI_SEGMENT_LIB_ADDRESS (
- DEFAULT_PCI_SEGMENT_NUMBER_PCH,
- DEFAULT_PCI_BUS_NUMBER_PCH,
- PCI_DEVICE_NUMBER_PCH_LAN,
- PCI_FUNCTION_NUMBER_PCH_LAN,
- 0
- );
- if (PciSegmentRead16 (LanRegBase + PCI_VENDOR_ID_OFFSET) == 0xFFFF) {
- return;
- }
- //
- // Check if GbE device is in D0
- //
- if ((PciSegmentRead16 (LanRegBase + R_LAN_CFG_PMCS) & B_LAN_CFG_PMCS_PS) != V_LAN_CFG_PMCS_PS0) {
- return;
- }
- ASSERT (mResvMmioSize >= (1 << N_LAN_CFG_MBARA_ALIGN));
- GbeBar = (UINT32) mResvMmioBaseAddr;
- if (GbeBar == 0) {
- ASSERT (FALSE);
- return;
- }
- //
- // Enable MMIO decode using reserved range.
- //
- PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
- PciSegmentWrite32 (LanRegBase + R_LAN_CFG_MBARA, GbeBar);
- PciSegmentOr16 (LanRegBase + PCI_COMMAND_OFFSET, EFI_PCI_COMMAND_MEMORY_SPACE);
- //
- // If MBARA offset 5800h [0] = 1b then proceed with the w/a
- //
- if (MmioRead32 (GbeBar + R_LAN_MEM_CSR_WUC) & B_LAN_MEM_CSR_WUC_APME) {
- Status = GbeMdiAcquireMdio (GbeBar);
- ASSERT_EFI_ERROR (Status);
- if (!EFI_ERROR (Status)) {
- GbeWolWorkaround (GbeBar);
- GbeMdiReleaseMdio (GbeBar);
- }
- }
- //
- // Disable MMIO decode.
- //
- PciSegmentAnd16 (LanRegBase + PCI_COMMAND_OFFSET, (UINT16) ~EFI_PCI_COMMAND_MEMORY_SPACE);
- PciSegmentWrite32 (LanRegBase + R_LAN_CFG_MBARA, 0);
- }
- /**
- Enable platform wake from LAN when in DeepSx if platform supports it.
- Called upon Sx entry.
- **/
- VOID
- GbeConfigureDeepSxWake (
- VOID
- )
- {
- if (PmcIsLanDeepSxWakeEnabled ()) {
- IoOr32 ((UINTN) (mAcpiBaseAddr + R_ACPI_IO_GPE0_EN_127_96), (UINT32) B_ACPI_IO_GPE0_EN_127_96_LAN_WAKE);
- }
- }
- /**
- GbE Sx entry handler
- **/
- VOID
- PchLanSxCallback (
- VOID
- )
- {
- if (IsGbeEnabled ()) {
- GbeSxWorkaround ();
- GbeConfigureDeepSxWake ();
- }
- }
|