974 lines
24 KiB
C
974 lines
24 KiB
C
/**@file
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 1999 - 2021 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains a 'Sample Driver' and is licensed as such under the terms
|
|
of your license agreement with Intel or your vendor. This file may be modified
|
|
by the user, subject to the additional terms of the license agreement.
|
|
|
|
@par Specification Reference:
|
|
**/
|
|
|
|
|
|
//
|
|
// Module specific Includes
|
|
//
|
|
#include <PchPolicyCommon.h>
|
|
#include <Library/DevicePathLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/UefiBootServicesTableLib.h>
|
|
#include <Library/UefiRuntimeServicesTableLib.h>
|
|
#include <Library/SmmServicesTableLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Protocol/SmmGpiDispatch2.h>
|
|
#include <Protocol/LoadedImage.h>
|
|
#include <Protocol/SmmIoTrapDispatch2.h>
|
|
#include <Protocol/PchSmmIoTrapControl.h>
|
|
#include <Protocol/EcAccess.h>
|
|
#include <Library/AslUpdateLib.h>
|
|
#include <Protocol/SmmCpu.h>
|
|
#include <Protocol/SaPolicy.h>
|
|
#include <Library/ConfigBlockLib.h>
|
|
|
|
#include "EC.h"
|
|
#include "AcpiRes.h"
|
|
#include "Setup.h"
|
|
#include "PlatformBoardId.h"
|
|
#include <Library/GpioLib.h>
|
|
#include <Library/PmcLib.h>
|
|
#include <Register/GpioRegs.h>
|
|
#include <Register/CommonMsr.h>
|
|
#include <PlatformBoardType.h>
|
|
//[-start-211027-IB09480164-add]//
|
|
#include <Library/VariableLib.h>
|
|
//[-end-211027-IB09480164-add]//
|
|
|
|
//
|
|
// Global variables
|
|
//
|
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_GPI_DISPATCH2_PROTOCOL *mSmmGpiDispatch;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_SMM_CPU_PROTOCOL *mSmmCpu;
|
|
|
|
static EFI_EC_ACCESS_PROTOCOL mEcAccess;
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mGpioSmiPad = 0; // SMC_EXT_SMI GPIO pad
|
|
GLOBAL_REMOVE_IF_UNREFERENCED UINT32 mEcSlpS0Pad = 0; // EC_SLP_S0_CS GPIO pad
|
|
GLOBAL_REMOVE_IF_UNREFERENCED SA_POLICY_PROTOCOL *mSaPolicy;
|
|
GLOBAL_REMOVE_IF_UNREFERENCED GRAPHICS_DXE_CONFIG *mGraphicsDxeConfig;
|
|
|
|
//
|
|
// Magic number definition for values to be updated
|
|
//
|
|
#define UINT16_BIT_MAGIC_NUMBER 0xFFFF
|
|
|
|
//
|
|
// BugBug: add it since no A, B Segement available in SMM
|
|
//
|
|
#define TEMP_ADDRESS_BELOW_1M (0x00100000 - 16)
|
|
|
|
#define MAX_EC_RESPONSE_TIME_US 10000 // 10 ms- Worst case confirmed by EC
|
|
|
|
/**
|
|
EC get mother board ID
|
|
|
|
@param[in] FabID Pointer to a UINT8 buffer.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECGetMotherBoardID (
|
|
UINT8 *FabID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EcWriteCmd (SMC_FAB_ID);
|
|
Status = EcReadData (FabID);
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Get DSDT Table
|
|
//
|
|
VOID *GetDSDTTable (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_ACPI_DESCRIPTION_HEADER *Table;
|
|
UINTN Handle;
|
|
EFI_STATUS Status;
|
|
|
|
Handle = 0;
|
|
Status = LocateAcpiTableBySignature (
|
|
EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE,
|
|
(EFI_ACPI_DESCRIPTION_HEADER **) &Table,
|
|
&Handle
|
|
);
|
|
if (EFI_ERROR(Status) || (Table == NULL)) return 0;
|
|
return (VOID*)(UINTN)((EFI_ACPI_6_3_FIXED_ACPI_DESCRIPTION_TABLE *)Table)->Dsdt;
|
|
}
|
|
|
|
/**
|
|
Updates the Resource field(BaseAddress and Length) in _CRS Method
|
|
|
|
@param[in] BaseAddress Memory base address
|
|
@param[in] AddLength Address length
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS UpdateAslObj(
|
|
IN UINT16 BaseAddress,
|
|
IN UINT8 AddLength
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_ACPI_DESCRIPTION_HEADER *DsdtTable;
|
|
UINT32 Length;
|
|
UINT8 *ptr;
|
|
UINT8 *pPRScope;
|
|
UINT8 Index;
|
|
UINT32 *Signature;
|
|
|
|
ASL_OBJ_INFO ObjInfo;
|
|
|
|
DsdtTable = (EFI_ACPI_DESCRIPTION_HEADER *) GetDSDTTable();
|
|
if (!DsdtTable) {
|
|
DEBUG ((DEBUG_ERROR,"DSDT Table not found.\n"));
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
Length = DsdtTable->Length - sizeof(EFI_ACPI_DESCRIPTION_HEADER);
|
|
ptr = (UINT8*)DsdtTable + sizeof(EFI_ACPI_DESCRIPTION_HEADER);
|
|
|
|
// Locate _SB scope
|
|
Status = GetAslObj(ptr, Length, (UINT8 *) "_SB", otScope, &ObjInfo);
|
|
if (EFI_ERROR(Status)) {
|
|
DEBUG ((DEBUG_ERROR,"Scope _SB not found.\n"));
|
|
return Status;
|
|
}
|
|
pPRScope = (UINT8 *) ObjInfo.DataStart;
|
|
|
|
// Locate PMSC Device
|
|
Status = GetAslObj(pPRScope, Length, (UINT8 *) "LDRC", otDevice, &ObjInfo);
|
|
if (EFI_ERROR(Status)) {
|
|
DEBUG ((DEBUG_ERROR,"Device LDRC not found.\n"));
|
|
return Status;
|
|
}
|
|
|
|
//
|
|
// Conditional match. Search _CSR in Device (PMSC).
|
|
//
|
|
for (ptr = (UINT8 *)ObjInfo.DataStart; ptr <= (UINT8 *)ObjInfo.DataStart + ObjInfo.Length; ptr++) {
|
|
//
|
|
// Get a pointer to compare for signature
|
|
//
|
|
Signature = (UINT32*) ptr;
|
|
|
|
//
|
|
// Check if the signature is "_CRS"
|
|
//
|
|
if ((*Signature) == 0x5352435F) {
|
|
|
|
//
|
|
// Now look for an empty resource entry, fix the base address and length fields
|
|
//
|
|
for (Index = 0; *(UINT16*) (ptr + 9 + 8 * Index) != 0x0079; Index++) {
|
|
//
|
|
// Abstract: Modify _CRS package algorithm
|
|
//
|
|
if (*(UINT16*) (ptr + 11 + 8 * Index) == UINT16_BIT_MAGIC_NUMBER) {
|
|
//
|
|
// Fixup the Base Address and Length.
|
|
//
|
|
*(UINT16*) (ptr + 11 + 8 * Index) = BaseAddress;
|
|
*(UINT16*) (ptr + 13 + 8 * Index) = BaseAddress;
|
|
*(ptr + 16 + 8 * Index) = AddLength;
|
|
//
|
|
// Abstract End
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Switch EC to ACPI Mode.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECEnableACPIMode (
|
|
VOID
|
|
)
|
|
{
|
|
// ECDisableSMINotify();
|
|
EcWriteCmd (SMC_SMI_DISABLE);
|
|
EcWriteCmd (SMC_ENABLE_ACPI_MODE);
|
|
if (mGraphicsDxeConfig->AlsEnable != 0) {
|
|
EcWriteCmd (SMC_ALS_ENABLE);
|
|
EcWriteData(0x01); // enable ALS
|
|
}
|
|
else {
|
|
EcWriteCmd (SMC_ALS_ENABLE);
|
|
EcWriteData(0x00); // disable ALS
|
|
}
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
Switch EC to Non-ACPI Mode.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECDisableACPIMode (
|
|
VOID
|
|
)
|
|
{
|
|
EcWriteCmd (SMC_DISABLE_ACPI_MODE);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
EC disable SMI notify.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECDisableSMINotify (
|
|
VOID
|
|
)
|
|
{
|
|
EcWriteCmd (SMC_DISABLE_SMI_NOTIFY);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
EC enable SMI notify.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECEnableSMINotify (
|
|
VOID
|
|
)
|
|
{
|
|
EcWriteCmd (SMC_ENABLE_SMI_NOTIFY);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
EC shut down system.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECShutDownSystem (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EcWriteCmd (SMC_SYSTEM_POWER_OFF);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
Switch EC to ACPI Mode.
|
|
|
|
@param[in] Revision
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECGetECVersion (
|
|
UINT8 *Revision
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EcWriteCmd (SMC_READ_REVISION);
|
|
Status = EcReadData (Revision);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
EC enable Lan.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECEnableLan (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EcWriteCmd (SMC_LAN_ON);
|
|
return Status;
|
|
}
|
|
|
|
|
|
/**
|
|
EC disable Lan.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECDisableLan (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EcWriteCmd (SMC_LAN_OFF);
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
EC deep Sx config.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
ECDeepSxConfig(
|
|
UINT8 EcData
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EcWriteCmd (SMC_DEEPSX_CMD);
|
|
Status = EcWriteData (EcData);
|
|
DEBUG ((DEBUG_INFO, "ECDeepSxConfig: %x\n", EcData));
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
EC turbo ctrl mode.
|
|
|
|
@param[in] Enable Enable / Disable turbo ctrl test mode
|
|
@param[in] ACBrickCap Data of AC Brick Capacity
|
|
@param[in] ECPollPeriod Data of EC Poll Period
|
|
@param[in] ECGuardBandValue Value of EC Guard Band
|
|
@param[in] ECAlgorithmSel Value of EC Algorithm Selection
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcTurboCtrlMode(
|
|
UINT8 Enable,
|
|
UINT8 ACBrickCap,
|
|
UINT8 ECPollPeriod,
|
|
UINT8 ECGuardBandValue,
|
|
UINT8 ECAlgorithmSel
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
|
|
if (Enable) {
|
|
Status = EcWriteCmd (SMC_TURBOCTRL_TESTMODE_ENABLE);
|
|
Status = EcWriteData (ACBrickCap);
|
|
Status = EcWriteData (ECPollPeriod);
|
|
Status = EcWriteData (ECGuardBandValue);
|
|
Status = EcWriteData (ECAlgorithmSel);
|
|
} else {
|
|
Status = EcWriteCmd (SMC_TURBOCTRL_TESTMODE_DISABLE);
|
|
}
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
/**
|
|
Allow EC to control fan when OS is hung.
|
|
|
|
@param[in] CpuTemp
|
|
@param[in] CpuFanSpeed
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcFailSafeFanCtrl(
|
|
UINT8 CpuTemp,
|
|
UINT8 CpuFanSpeed
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EcWriteCmd (SMC_FAIL_SAFE_FAN_CTRL);
|
|
Status = EcWriteData (CpuTemp);
|
|
Status = EcWriteData (CpuFanSpeed);
|
|
|
|
return Status;
|
|
}
|
|
|
|
VOID mMicroSecondDelay(UINTN Delay)
|
|
{
|
|
gBS->Stall(Delay);
|
|
}
|
|
|
|
/**
|
|
Read Data from EC data Port.
|
|
|
|
@param[in] pData Pointer to a UINT8 buffer.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcNonBlockReadData (
|
|
UINT8 *pData
|
|
)
|
|
{
|
|
UINT8 Status;
|
|
UINT32 Counter;
|
|
|
|
Counter = MAX_EC_RESPONSE_TIME_US;
|
|
do {
|
|
gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT8, EcCommandPort, 1, &Status);
|
|
mMicroSecondDelay(1);
|
|
Counter--;
|
|
} while (!(Status & 1) && (Counter>0));
|
|
DEBUG ((DEBUG_INFO, "EcNonBlockReadData Command %d us\n", (MAX_EC_RESPONSE_TIME_US-Counter)));
|
|
if (!(Status & 1)) // Counter is zero but the O/p buffer is still
|
|
{
|
|
DEBUG ((DEBUG_ERROR, "EcNonBlockReadData Timeout %d us\n", (MAX_EC_RESPONSE_TIME_US-Counter)));
|
|
return EFI_TIMEOUT;
|
|
}
|
|
gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT8, EcDataPort, 1, pData);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Detect EC specific DTT participants
|
|
|
|
@param[out] DataBuffer
|
|
|
|
@retval EFI_SUCCESS Command success
|
|
@retval EFI_DEVICE_ERROR Command error
|
|
**/
|
|
EFI_STATUS
|
|
DetectEcDttParticipants (
|
|
OUT UINT8 *DataBuffer
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
Status = EcWriteCmd(SMC_GET_EC_DTT_DEVICES);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = EcNonBlockReadData (&DataBuffer[0]);
|
|
if (!EFI_ERROR (Status)) {
|
|
Status = EcNonBlockReadData (&DataBuffer[1]);
|
|
}
|
|
}
|
|
|
|
return Status;
|
|
}
|
|
|
|
/**
|
|
EC initializes.
|
|
|
|
@param[in] ImageHandle Image handle of this driver.
|
|
@param[in] SystemTable Pointer to the System Table.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
@retval EFI_UNSUPPORTED Install protocol failure.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
InitializeEcSmm (
|
|
IN EFI_HANDLE ImageHandle,
|
|
IN EFI_SYSTEM_TABLE *SystemTable
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
EFI_STATUS Status2;
|
|
EFI_STATUS Status3;
|
|
EFI_STATUS Status4;
|
|
SA_SETUP SaSetup;
|
|
PCH_SETUP PchSetup;
|
|
SETUP_DATA SetupData;
|
|
UINTN VariableSize;
|
|
CPU_SETUP CpuSetup;
|
|
UINT8 EcPowerFeatures;
|
|
UINT8 DataBuffer[2];
|
|
UINT8 i;
|
|
UINT8 SensorData;
|
|
UINT8 FanData;
|
|
UINT32 VariableAttributes;
|
|
//[-start-211027-IB09480164-add]//
|
|
UINTN SetupInitFlagSize;
|
|
UINT8 SetupInitFlag;
|
|
EFI_STATUS GetSetupStatus;
|
|
//[-end-211027-IB09480164-add]//
|
|
|
|
Status = gSmst->SmmLocateProtocol(&gEfiSmmCpuProtocolGuid, NULL, (VOID **) &mSmmCpu);
|
|
ASSERT_EFI_ERROR(Status);
|
|
|
|
if ((PcdGetBool (PcdEcPresent) == FALSE) ||
|
|
(PcdGet8 (PcdPlatformFlavor) == FlavorWorkstation) ||
|
|
(PcdGet8 (PcdBoardType) == BoardTypeSv)
|
|
) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
mEcAccess.Handle = NULL;
|
|
mEcAccess.QuerryCmd = EcQueryCommand;
|
|
mEcAccess.WriteCmd = EcWriteCmd;
|
|
mEcAccess.WriteData = EcWriteData;
|
|
mEcAccess.ReadData = EcReadData;
|
|
mEcAccess.ReadMem = EcReadMem;
|
|
mEcAccess.WriteMem = EcWriteMem;
|
|
mEcAccess.AcpiEnable = ECEnableACPIMode;
|
|
mEcAccess.AcpiDisable = ECDisableACPIMode;
|
|
mEcAccess.SMINotifyEnable = ECEnableSMINotify;
|
|
mEcAccess.SMINotifyDisable = ECDisableSMINotify;
|
|
mEcAccess.ShutDownSystem = ECShutDownSystem;
|
|
mEcAccess.GetMotherBoardID = ECGetMotherBoardID;
|
|
mEcAccess.GetECVersion = ECGetECVersion;
|
|
mEcAccess.EnableLan = ECEnableLan;
|
|
mEcAccess.DisableLan = ECDisableLan;
|
|
mEcAccess.DeepSxConfig = ECDeepSxConfig;
|
|
mEcAccess.TurboCtrlMode = EcTurboCtrlMode;
|
|
mEcAccess.GetSwitchStatus = EcGetSwitchStatus;
|
|
mEcAccess.FailSafeFanCtrl = EcFailSafeFanCtrl;
|
|
|
|
Status = gSmst->SmmInstallProtocolInterface (
|
|
&mEcAccess.Handle,
|
|
&gEcAccessProtocolGuid,
|
|
EFI_NATIVE_INTERFACE,
|
|
&mEcAccess
|
|
);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "InstallMultipleProtocolInterfaces returned %r\n", Status));
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_ERROR, "Couldn't register the EC SMI handler. Status: %r\n", Status));
|
|
return Status;
|
|
}
|
|
|
|
EcWriteCmd (SMC_DISABLE_ACPI_MODE);
|
|
EcWriteCmd (SMC_ENABLE_POWER_SWITCH);
|
|
EcWriteCmd (SMC_ENABLE_SMI_NOTIFY);
|
|
EcWriteCmd (SMC_SMI_ENABLE);
|
|
EcWriteCmd (SMC_SET_ETM_COMMAND);
|
|
|
|
//
|
|
// Locate our shared data area
|
|
//
|
|
Status = gBS->LocateProtocol (&gSaPolicyProtocolGuid, NULL, (VOID **) &mSaPolicy);
|
|
ASSERT_EFI_ERROR (Status);
|
|
Status = GetConfigBlock ((VOID *) mSaPolicy, &gGraphicsDxeConfigGuid, (VOID *) &mGraphicsDxeConfig);
|
|
|
|
ASSERT_EFI_ERROR (Status);
|
|
|
|
|
|
VariableSize = sizeof (SETUP_DATA);
|
|
Status = gRT->GetVariable (
|
|
(CHAR16 *) L"Setup",
|
|
&gSetupVariableGuid,
|
|
&VariableAttributes,
|
|
&VariableSize,
|
|
&SetupData
|
|
);
|
|
|
|
VariableSize = sizeof (SA_SETUP);
|
|
Status2 = gRT->GetVariable (
|
|
(CHAR16 *) L"SaSetup",
|
|
&gSaSetupVariableGuid,
|
|
(UINT32 *) NULL,
|
|
&VariableSize,
|
|
&SaSetup
|
|
);
|
|
|
|
VariableSize = sizeof (CPU_SETUP);
|
|
Status3 = gRT->GetVariable (
|
|
(CHAR16 *) L"CpuSetup",
|
|
&gCpuSetupVariableGuid,
|
|
(UINT32 *) NULL,
|
|
&VariableSize,
|
|
&CpuSetup
|
|
);
|
|
|
|
VariableSize = sizeof (PCH_SETUP);
|
|
Status4 = gRT->GetVariable (
|
|
(CHAR16 *) L"PchSetup",
|
|
&gPchSetupVariableGuid,
|
|
(UINT32 *) NULL,
|
|
&VariableSize,
|
|
&PchSetup
|
|
);
|
|
|
|
if (!EFI_ERROR (Status) && !EFI_ERROR (Status2) && !EFI_ERROR (Status3) && !EFI_ERROR (Status4)) {
|
|
EcWriteCmd (SMC_SET_SHUTDOWN_TEMP);
|
|
//
|
|
// Use Critical Trip Point from Setup
|
|
//
|
|
EcWriteData (SetupData.CriticalThermalTripPoint);
|
|
|
|
//
|
|
// Detect DTT EC based devices
|
|
//
|
|
Status = DetectEcDttParticipants((UINT8 *)DataBuffer);
|
|
|
|
if (!EFI_ERROR (Status)) {
|
|
FanData= DataBuffer[0];
|
|
SensorData = DataBuffer[1];
|
|
DEBUG ((DEBUG_INFO, "EC Fan data %x\n", FanData));
|
|
DEBUG ((DEBUG_INFO, "EC Sensor data %x\n", SensorData));
|
|
// Special Condition. CPU Fan 1 is enabled by default in PlatformSetup.hfr. Need to disable it, if Fan 1 is not detected by the EC
|
|
if(!(FanData & 0x01))
|
|
{
|
|
SetupData.EnableFan1Device = 0;
|
|
}
|
|
}
|
|
else {
|
|
FanData = 0x01; // Default CPU Fan
|
|
SensorData = 0x1E; // Default Sensor 2-5
|
|
}
|
|
|
|
for(i=0; i<MAX_EC_FANS; i++) {
|
|
if(FanData & (0x01<<i)) {
|
|
SetupData.DetectEcFan[i] = TRUE;
|
|
DEBUG ((DEBUG_INFO, "EC Fan %d detected\n", i+1));
|
|
}
|
|
else {
|
|
SetupData.DetectEcFan[i] = FALSE;
|
|
DEBUG ((DEBUG_INFO, "EC Fan %d supressed\n", i+1));
|
|
}
|
|
}
|
|
|
|
for(i=0; i<MAX_EC_SENSORS; i++) {
|
|
if(SensorData & (0x01<<i)) {
|
|
SetupData.DetectEcSensors[i] = TRUE;
|
|
DEBUG ((DEBUG_INFO, "EC Sensor %d detected\n", i+1));
|
|
}
|
|
else {
|
|
SetupData.DetectEcSensors[i] = FALSE;
|
|
DEBUG ((DEBUG_INFO, "EC Sensor %d supressed\n", i+1));
|
|
}
|
|
}
|
|
//[-start-211027-IB09480164-add]//
|
|
GetSetupStatus = EFI_SUCCESS;
|
|
if (!IsVariableInVariableStoreRegion (L"Setup", &gSetupVariableGuid)) {
|
|
GetSetupStatus = EFI_NOT_FOUND;
|
|
}
|
|
//[-end-211027-IB09480164-add]//
|
|
VariableSize = sizeof (SETUP_DATA);
|
|
Status = gRT->SetVariable (
|
|
L"Setup",
|
|
&gSetupVariableGuid,
|
|
VariableAttributes,
|
|
VariableSize,
|
|
&SetupData
|
|
);
|
|
ASSERT_EFI_ERROR(Status);
|
|
|
|
//[-start-211027-IB09480164-add]//
|
|
if (!EFI_ERROR(Status) && (GetSetupStatus == EFI_NOT_FOUND)) {
|
|
SetupInitFlagSize = sizeof (SetupInitFlag);
|
|
SetupInitFlag = 1;
|
|
Status = gRT->SetVariable (
|
|
L"SetupInitFlag",
|
|
&gSetupVariableGuid,
|
|
EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
|
|
SetupInitFlagSize,
|
|
&SetupInitFlag
|
|
);
|
|
ASSERT_EFI_ERROR(Status);
|
|
}
|
|
//[-end-211027-IB09480164-add]//
|
|
|
|
//
|
|
//Send the command to EC to enable reporting memory temperatures to the processor via PECI.
|
|
//
|
|
EcWriteCmd (SMC_SET_PECI_INJECTED_TEMP);
|
|
EcWriteData (SaSetup.PeciInjectedTemp);
|
|
//
|
|
// Send the command to put the EC into low power mode if it is enabled in setup
|
|
//
|
|
EcPowerFeatures = 0;
|
|
if (SetupData.LowPowerS0Idle && SetupData.EcLowPowerMode && SetupData.CSNotifyEC) {
|
|
EcPowerFeatures |= EC_DEBUG_LOW_POWER_ENABLE;
|
|
}
|
|
if (SetupData.EcDebugLed){
|
|
EcPowerFeatures |= EC_DEBUG_LED_DISABLE;
|
|
}
|
|
if (SetupData.ECBaseCsPwrPolicy){
|
|
EcPowerFeatures |= EC_DEBUG_BASE_PCS_PWR_POLICY;
|
|
}
|
|
|
|
EcWriteCmd (EC_POWER_FEATURES_CMD);
|
|
EcWriteData (EcPowerFeatures);
|
|
|
|
// Program EC based on Pseudo G3 State
|
|
EcWriteCmd(SMC_PSEUDO_G3_CMD);
|
|
if (SetupData.PseudoG3State) {
|
|
EcWriteData(0x01);
|
|
} else {
|
|
EcWriteData(0x00);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "Setup DeepSx Mode: %x\n", PchSetup.DeepSxMode));
|
|
switch(PchSetup.DeepSxMode) {
|
|
case PchDeepSxPolDisable:
|
|
mEcAccess.DeepSxConfig(0x00);
|
|
break;
|
|
case PchDpS5BatteryEn:
|
|
mEcAccess.DeepSxConfig(0x01);
|
|
break;
|
|
case PchDpS5AlwaysEn:
|
|
mEcAccess.DeepSxConfig(0x02);
|
|
break;
|
|
case PchDpS4S5BatteryEn:
|
|
mEcAccess.DeepSxConfig(0x03);
|
|
break;
|
|
case PchDpS4S5AlwaysEn:
|
|
mEcAccess.DeepSxConfig(0x04);
|
|
break;
|
|
default:
|
|
mEcAccess.DeepSxConfig(0x00);
|
|
}
|
|
if (CpuSetup.EcTurboControlMode) {
|
|
mEcAccess.TurboCtrlMode(TRUE, CpuSetup.AcBrickCapacity, CpuSetup.EcPollingPeriod,
|
|
CpuSetup.EcGuardBandValue, CpuSetup.EcAlgorithmSel);
|
|
} else {
|
|
mEcAccess.TurboCtrlMode(FALSE, 0x00, 0x00, 0x00, 0x00);
|
|
}
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
/**
|
|
Read the EC Query Value
|
|
|
|
@param[in] pQdata Pointer to a UINT8 buffer.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcQueryCommand (
|
|
UINT8 *pQdata
|
|
)
|
|
{
|
|
EcWriteCmd (SMC_QUERY_SMI);
|
|
EcReadData (pQdata);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Wait till EC I/P buffer is free.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EcIbFree (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Status;
|
|
do {
|
|
gSmst->SmmIo.Io.Read( &gSmst->SmmIo,
|
|
SMM_IO_UINT8,
|
|
EcCommandPort,
|
|
1,
|
|
&Status);
|
|
} while (Status & 2);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Wait till EC O/P buffer is full
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EcObFull (
|
|
VOID
|
|
)
|
|
{
|
|
UINT8 Status;
|
|
do {
|
|
gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT8, EcCommandPort, 1, &Status);
|
|
} while (!(Status & 1));
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
/**
|
|
Send EC command
|
|
|
|
@param[in] cmd Writing command to EC's command port.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcWriteCmd (
|
|
UINT8 cmd
|
|
)
|
|
{
|
|
EcIbFree();
|
|
gSmst->SmmIo.Io.Write( &gSmst->SmmIo,
|
|
SMM_IO_UINT8,
|
|
EcCommandPort,
|
|
1,
|
|
&cmd);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Write Data from EC data port
|
|
|
|
@param[in] data Writing data to EC's data port.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcWriteData (
|
|
UINT8 data
|
|
)
|
|
{
|
|
EcIbFree();
|
|
gSmst->SmmIo.Io.Write( &gSmst->SmmIo,
|
|
SMM_IO_UINT8,
|
|
EcDataPort,
|
|
1,
|
|
&data);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Read Data from EC data Port.
|
|
|
|
@param[in] pData Pointer to a UINT8 buffer.
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcReadData (
|
|
UINT8 *pData
|
|
)
|
|
{
|
|
if (EFI_ERROR(EcObFull())) return EFI_DEVICE_ERROR;
|
|
gSmst->SmmIo.Io.Read( &gSmst->SmmIo, SMM_IO_UINT8, EcDataPort, 1, pData);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Read Data from EC Memory from location pointed by Index.
|
|
|
|
@param[in] Index Index of the read data
|
|
@param[in] Data Data to be read
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcReadMem (
|
|
UINT8 Index,
|
|
UINT8 *Data
|
|
)
|
|
{
|
|
UINT8 cmd = SMC_READ_EC;
|
|
EcWriteCmd (cmd);
|
|
EcWriteData(Index);
|
|
EcReadData(Data);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
|
|
/**
|
|
Write Data to EC memory at location pointed by Index.
|
|
|
|
@param[in] Index Index of the written data
|
|
@param[in] Data Data to be written
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcWriteMem (
|
|
UINT8 Index,
|
|
UINT8 Data
|
|
)
|
|
{
|
|
UINT8 cmd = SMC_WRITE_EC;
|
|
EcWriteCmd (cmd);
|
|
EcWriteData(Index);
|
|
EcWriteData(Data);
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
/**
|
|
Get the info from EC on Developer Mode / Recovery Mode switch.
|
|
EC will return 0 in bit3 when the Recovery Mode switch is pressed and
|
|
will return 0 in bit6 when Developer Mode switch is pressed.
|
|
|
|
@param[in] Data Read data from EC
|
|
|
|
@retval EFI_SUCCESS Function successfully executed.
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
EcGetSwitchStatus (
|
|
UINT8 *Data
|
|
)
|
|
{
|
|
UINT8 cmd = SMC_GET_SWITCH_STATUS;
|
|
EcWriteCmd (cmd);
|
|
EcReadData(Data);
|
|
return EFI_SUCCESS;
|
|
}
|