204 lines
4.8 KiB
C
204 lines
4.8 KiB
C
/*****************************************************************************
|
|
*
|
|
*
|
|
* Copyright (c) 2012 - 2015, Hefei LCFC Information Technology Co.Ltd.
|
|
* And/or its affiliates. All rights reserved.
|
|
* Hefei LCFC Information Technology Co.Ltd. PROPRIETARY/CONFIDENTIAL.
|
|
* Use is subject to license terms.
|
|
*
|
|
*****************************************************************************/
|
|
/*
|
|
Data Name Version Description
|
|
2014.12.28 dahai.zhou v1.00 Initial release it for EDK2 projects
|
|
*/
|
|
|
|
#include <Library/IoLib.h>
|
|
#include <Library/PcdLib.h>
|
|
#include <Uefi.h>
|
|
#include <Lfc.h>
|
|
#include <Library/GpioLib.h>
|
|
//[-start-210513-KEBIN00001-modify]//
|
|
//#include "Register/PchRegsPcr.h"
|
|
#include "Register/PchPcrRegs.h"
|
|
//[-end-210513-KEBIN00001-modify]//
|
|
#include <Library/PchPcrLib.h>
|
|
|
|
#define PCH_PCR_BASE_ADDRESS 0xFD000000 ///< SBREG MMIO base address
|
|
#define ACPI_TIMER_ADDR (PcdGet16(PcdPerfPkgAcpiIoPortBaseAddress) + 0x08)
|
|
#define ACPI_TIMER_MAX_VALUE 0x1000000
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LfcLibLogError (
|
|
IN UINT8 Data
|
|
)
|
|
{
|
|
UINT8 ErrorCount;
|
|
|
|
IoWrite8 (LFC_CMOS_INDEX, LFC_DEBUG_ERROR_COUNT_INDEX);
|
|
ErrorCount = IoRead8 (LFC_CMOS_DATA);
|
|
|
|
ErrorCount++;
|
|
|
|
IoWrite8 (LFC_CMOS_INDEX, LFC_DEBUG_ERROR_COUNT_INDEX);
|
|
IoWrite8 (LFC_CMOS_DATA, ErrorCount);
|
|
|
|
if (ErrorCount > 3) {
|
|
return EFI_SUCCESS;
|
|
} else {
|
|
IoWrite8 (LFC_CMOS_INDEX, LFC_DEBUG_ERROR1_INDEX + ErrorCount - 1);
|
|
IoWrite8 (LFC_CMOS_DATA, Data);
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
//[-start-210722-QINGLIN0002-modify]//
|
|
//[-start-210830-GEORGE0001-modify]//
|
|
//#ifndef S570_SUPPORT
|
|
#if !defined(S570_SUPPORT) && !defined(S77014_SUPPORT) && !defined(S77014IAH_SUPPORT)
|
|
//[-end-210830-GEORGE0001-modify]//
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LfcProjectLibSetDGPUPowerEN (
|
|
UINT8 Level
|
|
)
|
|
{
|
|
UINT32 Data32;
|
|
// DGPU POEWR_EN GPP_C12 offset 0x6C0
|
|
// Set Tx to level.
|
|
|
|
Data32 = MmioRead32 (PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6C0));
|
|
Data32 &= ~BIT0;
|
|
Data32 |= Level & BIT0;
|
|
|
|
MmioWrite32(PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6C0), Data32);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LfcProjectLibSetDGPUPowerRST (
|
|
UINT8 Level
|
|
)
|
|
{
|
|
UINT32 Data32;
|
|
// DGPU POEWR_RST GPP_C13 offset 0x6D0
|
|
// Set Tx to level.
|
|
|
|
Data32 = MmioRead32 (PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6D0));
|
|
|
|
Data32 &= ~BIT0;
|
|
Data32 |= Level & BIT0;
|
|
|
|
MmioWrite32(PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6D0), Data32);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
//
|
|
//disable Gpio's Tx, for power save and HW circuit.
|
|
//there have pull up by HW on PXS_PwrEn.
|
|
//
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LfcProjectLibDisableGPUPwr (
|
|
)
|
|
{
|
|
UINT32 Data32;
|
|
|
|
//disable PXS_PwrEn output
|
|
Data32 = MmioRead32 (PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6C0));
|
|
Data32 |= BIT8;
|
|
MmioWrite32(PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6C0), Data32);
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LfcProjectLibGetDGPUPowerGood (
|
|
UINT8 *PowerGood
|
|
)
|
|
{
|
|
// DGPU POEWR_RST GPP_C14 offset 0x6E0
|
|
// Get Rx to PowerGood.
|
|
if(MmioRead32 (PCH_PCR_ADDRESS (PID_GPIOCOM4, 0x6E0)) & BIT1) {
|
|
// Power Good equ high
|
|
*PowerGood = 1;
|
|
}
|
|
else {
|
|
// Power Good equ low
|
|
*PowerGood = 0;
|
|
}
|
|
return EFI_SUCCESS;
|
|
}
|
|
#endif
|
|
//[-end-210722-QINGLIN0002-modify]//
|
|
|
|
/**
|
|
|
|
Waits for at least the given number of microseconds.
|
|
|
|
@param[in] Microseconds - Desired length of time to wait
|
|
|
|
@retval EFI_SUCCESS - If the desired amount of time passed.
|
|
@retval !EFI_SUCCESS - If error occurs while locating CpuIoPpi.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
LfcProjectLibStall (
|
|
IN UINTN Microseconds
|
|
)
|
|
{
|
|
UINT32 CurrentTick;
|
|
UINT32 OriginalTick;
|
|
UINT32 RemainingTick;
|
|
UINTN Counts;
|
|
UINTN Ticks;
|
|
|
|
if (Microseconds == 0) {
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
OriginalTick = IoRead32 (ACPI_TIMER_ADDR) & 0x00FFFFFF;
|
|
|
|
CurrentTick = OriginalTick;
|
|
|
|
//
|
|
// The timer frequency is 3.579545 MHz, so 1 ms corresponds 3.58 clocks
|
|
//
|
|
Ticks = Microseconds * 358 / 100 + OriginalTick + 1;
|
|
//
|
|
// The loops needed by timer overflow
|
|
//
|
|
Counts = Ticks / ACPI_TIMER_MAX_VALUE;
|
|
//
|
|
// remaining clocks within one loop
|
|
//
|
|
RemainingTick = Ticks % ACPI_TIMER_MAX_VALUE;
|
|
//
|
|
// not intend to use TMROF_STS bit of register PM1_STS, because this adds extra
|
|
// one I/O operation, and maybe generate SMI
|
|
//
|
|
while (Counts != 0) {
|
|
CurrentTick = IoRead32 (ACPI_TIMER_ADDR) & 0x00FFFFFF;
|
|
|
|
if (CurrentTick <= OriginalTick) {
|
|
Counts--;
|
|
}
|
|
|
|
OriginalTick = CurrentTick;
|
|
}
|
|
|
|
while ((RemainingTick > CurrentTick) && (OriginalTick <= CurrentTick)) {
|
|
OriginalTick = CurrentTick;
|
|
CurrentTick = (IoRead32 (ACPI_TIMER_ADDR) & 0x00FFFFFF);
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|