QuarkSocPkg: Add new package for Quark SoC X1000
Changes for V4 ============== 1) Remove Unicode character from C source file 2) Move delete of QuarkSocPkg\QuarkNorthCluster\Binary\QuarkMicrocode from QuarkPlatformPkg commit to QuarkSocPkg commit Changes for V2 ============== 1) Sync with new APIs in SmmCpuFeaturesLib class 2) Use new generic PCI serial driver PciSioSerialDxe in MdeModulePkg 3) Remove PCI serial driver from QuarkSocPkg 4) Apply optimizations to MtrrLib from MtrrLib in UefiCpuPkg 5) Convert all UNI files to utf-8 6) Replace tabs with spaces and remove trailing spaces 7) Add License.txt Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Michael Kinney <michael.d.kinney@intel.com> Acked-by: Jordan Justen <jordan.l.justen@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@19286 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
/** @file
|
||||
Common header file shared by all source files.
|
||||
|
||||
This file includes package header files, library classes and protocol, PPI & GUID definitions.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
**/
|
||||
|
||||
#ifndef __COMMON_HEADER_H_
|
||||
#define __COMMON_HEADER_H_
|
||||
|
||||
|
||||
|
||||
#include <PiPei.h>
|
||||
#include <IntelQNCBase.h>
|
||||
|
||||
#include <Library/IntelQNCLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/CpuLib.h>
|
||||
#include <Library/PciCf8Lib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PciLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
#include <IndustryStandard/Pci22.h>
|
||||
|
||||
#endif
|
777
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c
Normal file
777
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/IntelQNCLib.c
Normal file
@@ -0,0 +1,777 @@
|
||||
/** @file
|
||||
Lib function for Pei QNC.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
#include "CommonHeader.h"
|
||||
|
||||
/**
|
||||
This function provides the necessary SOC initialization
|
||||
before MRC running. It sets RCBA, GPIO, PMBASE
|
||||
and some parts of SOC through SOC message method.
|
||||
If the function cannot complete it'll ASSERT().
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
PeiQNCPreMemInit (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 RegValue;
|
||||
|
||||
// QNCPortWrite(Port#, Offset, Value)
|
||||
|
||||
//
|
||||
// Set the fixed PRI Status encodings config.
|
||||
//
|
||||
QNCPortWrite (
|
||||
QUARK_NC_MEMORY_ARBITER_SB_PORT_ID,
|
||||
QUARK_NC_MEMORY_ARBITER_REG_ASTATUS,
|
||||
QNC_FIXED_CONFIG_ASTATUS
|
||||
);
|
||||
|
||||
// Sideband register write to Remote Management Unit
|
||||
QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QNC_MSG_TMPM_REG_PMBA, (BIT31 | PcdGet16 (PcdPmbaIoBaseAddress)));
|
||||
|
||||
// Configurable I/O address in iLB (legacy block)
|
||||
|
||||
LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) = BIT31 | PcdGet16 (PcdSmbaIoBaseAddress);
|
||||
LpcPciCfg32 (R_QNC_LPC_GBA_BASE) = BIT31 | PcdGet16 (PcdGbaIoBaseAddress);
|
||||
LpcPciCfg32 (R_QNC_LPC_PM1BLK) = BIT31 | PcdGet16 (PcdPm1blkIoBaseAddress);
|
||||
LpcPciCfg32 (R_QNC_LPC_GPE0BLK) = BIT31 | PcdGet16 (PcdGpe0blkIoBaseAddress);
|
||||
LpcPciCfg32 (R_QNC_LPC_WDTBA) = BIT31 | PcdGet16 (PcdWdtbaIoBaseAddress);
|
||||
|
||||
//
|
||||
// Program RCBA Base Address
|
||||
//
|
||||
LpcPciCfg32AndThenOr (R_QNC_LPC_RCBA, (~B_QNC_LPC_RCBA_MASK), (((UINT32)(PcdGet64 (PcdRcbaMmioBaseAddress))) | B_QNC_LPC_RCBA_EN));
|
||||
|
||||
//
|
||||
// Program Memory Manager fixed config values.
|
||||
//
|
||||
|
||||
RegValue = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL);
|
||||
RegValue &= ~(DRAM_NON_HOST_RQ_LIMIT_MASK);
|
||||
RegValue |= (V_DRAM_NON_HOST_RQ_LIMIT << DRAM_NON_HOST_RQ_LIMIT_BP);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, QUARK_NC_MEMORY_MANAGER_BTHCTRL, RegValue);
|
||||
|
||||
//
|
||||
// Program iCLK fixed config values.
|
||||
//
|
||||
QncIClkAndThenOr (
|
||||
QUARK_ICLK_MUXTOP,
|
||||
(UINT32) ~(B_MUXTOP_FLEX2_MASK | B_MUXTOP_FLEX1_MASK),
|
||||
(V_MUXTOP_FLEX2 << B_MUXTOP_FLEX2_BP) | (V_MUXTOP_FLEX1 << B_MUXTOP_FLEX1_BP)
|
||||
);
|
||||
QncIClkAndThenOr (
|
||||
QUARK_ICLK_REF2_DBUFF0,
|
||||
(UINT32) ~(BIT0), // bit[0] cleared
|
||||
0
|
||||
);
|
||||
QncIClkOr (
|
||||
QUARK_ICLK_SSC1,
|
||||
BIT0 // bit[0] set
|
||||
);
|
||||
QncIClkOr (
|
||||
QUARK_ICLK_SSC2,
|
||||
BIT0 // bit[0] set
|
||||
);
|
||||
QncIClkOr (
|
||||
QUARK_ICLK_SSC3,
|
||||
BIT0 // bit[0] set
|
||||
);
|
||||
|
||||
//
|
||||
// Set RMU DMA disable bit post boot.
|
||||
//
|
||||
RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1);
|
||||
RegValue |= OPTIONS_1_DMA_DISABLE;
|
||||
QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_OPTIONS_1, RegValue);
|
||||
}
|
||||
|
||||
/**
|
||||
Do north cluster init which needs to be done AFTER MRC init.
|
||||
|
||||
@param VOID
|
||||
|
||||
@retval VOID
|
||||
**/
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
PeiQNCPostMemInit (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Program SVID/SID the same as VID/DID for all devices except root ports.
|
||||
//
|
||||
QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, R_EFI_PCI_SVID) = QNCMmPci32(0, MC_BUS, MC_DEV, MC_FUN, PCI_VENDOR_ID_OFFSET);
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_LPC, PCI_FUNCTION_NUMBER_QNC_LPC, PCI_VENDOR_ID_OFFSET);
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_0, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, R_EFI_PCI_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_QNC_IOSF2AHB_1, PCI_FUNCTION_NUMBER_QNC_IOSF2AHB, PCI_VENDOR_ID_OFFSET);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
Used to check QNC if it's S3 state. Clear the register state after query.
|
||||
|
||||
@retval TRUE if it's S3 state.
|
||||
@retval FALSE if it's not S3 state.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
QNCCheckS3AndClearState (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
BOOLEAN S3WakeEventFound;
|
||||
UINT16 Pm1Sts;
|
||||
UINT16 Pm1En;
|
||||
UINT16 Pm1Cnt;
|
||||
UINT32 Gpe0Sts;
|
||||
UINT32 Gpe0En;
|
||||
UINT32 NewValue;
|
||||
CHAR8 *EventDescStr;
|
||||
|
||||
S3WakeEventFound = FALSE;
|
||||
EventDescStr = NULL;
|
||||
|
||||
//
|
||||
// Read the ACPI registers,
|
||||
//
|
||||
Pm1Sts = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);
|
||||
Pm1En = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);
|
||||
Pm1Cnt = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
|
||||
Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);
|
||||
Gpe0En = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E);
|
||||
|
||||
//
|
||||
// Clear Power Management 1 Enable Register and
|
||||
// General Purpost Event 0 Enables Register
|
||||
//
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);
|
||||
IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);
|
||||
|
||||
if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S3) {
|
||||
|
||||
//
|
||||
// Detect the actual WAKE event
|
||||
//
|
||||
if ((Pm1Sts & B_QNC_PM1BLK_PM1S_RTC) && (Pm1En & B_QNC_PM1BLK_PM1E_RTC)) {
|
||||
EventDescStr = "RTC Alarm";
|
||||
S3WakeEventFound = TRUE;
|
||||
}
|
||||
if ((Pm1Sts & B_QNC_PM1BLK_PM1S_PCIEWSTS) && !(Pm1En & B_QNC_PM1BLK_PM1E_PWAKED)) {
|
||||
EventDescStr = "PCIe WAKE";
|
||||
S3WakeEventFound = TRUE;
|
||||
}
|
||||
if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_PCIE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_PCIE)) {
|
||||
EventDescStr = "PCIe";
|
||||
S3WakeEventFound = TRUE;
|
||||
}
|
||||
if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_GPIO) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_GPIO)) {
|
||||
EventDescStr = "GPIO";
|
||||
S3WakeEventFound = TRUE;
|
||||
}
|
||||
if ((Gpe0Sts & B_QNC_GPE0BLK_GPE0S_EGPE) && (Gpe0En & B_QNC_GPE0BLK_GPE0E_EGPE)) {
|
||||
EventDescStr = "Ext. GPE";
|
||||
S3WakeEventFound = TRUE;
|
||||
}
|
||||
if (S3WakeEventFound == FALSE) {
|
||||
EventDescStr = "Unknown";
|
||||
}
|
||||
DEBUG ((EFI_D_INFO, "S3 Wake Event - %a\n", EventDescStr));
|
||||
|
||||
//
|
||||
// If no Power Button Override event occurs and one enabled wake event occurs,
|
||||
// just do S3 resume and clear the state.
|
||||
//
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));
|
||||
|
||||
//
|
||||
// Set EOS to de Assert SMI
|
||||
//
|
||||
IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
|
||||
|
||||
//
|
||||
// Enable SMI globally
|
||||
//
|
||||
NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
|
||||
NewValue |= SMI_EN;
|
||||
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Used to check QNC if system wakes up from power on reset. Clear the register state after query.
|
||||
|
||||
@retval TRUE if system wakes up from power on reset
|
||||
@retval FALSE if system does not wake up from power on reset
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
QNCCheckPowerOnResetAndClearState (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT16 Pm1Sts;
|
||||
UINT16 Pm1Cnt;
|
||||
|
||||
//
|
||||
// Read the ACPI registers,
|
||||
// PM1_STS information cannot be lost after power down, unless CMOS is cleared.
|
||||
//
|
||||
Pm1Sts = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S);
|
||||
Pm1Cnt = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
|
||||
|
||||
//
|
||||
// If B_SLP_TYP is S5
|
||||
//
|
||||
if ((Pm1Sts & B_QNC_PM1BLK_PM1S_WAKE) != 0 && (Pm1Cnt & B_QNC_PM1BLK_PM1C_SLPTP) == V_S5) {
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, (Pm1Cnt & (~B_QNC_PM1BLK_PM1C_SLPTP)));
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is used to clear SMI and wake status.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCClearSmiAndWake (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Gpe0Sts;
|
||||
UINT32 SmiSts;
|
||||
|
||||
//
|
||||
// Read the ACPI registers
|
||||
//
|
||||
Gpe0Sts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S);
|
||||
SmiSts = IoRead32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
|
||||
|
||||
//
|
||||
// Clear any SMI or wake state from the boot
|
||||
//
|
||||
Gpe0Sts |= B_QNC_GPE0BLK_GPE0S_ALL;
|
||||
SmiSts |= B_QNC_GPE0BLK_SMIS_ALL;
|
||||
|
||||
//
|
||||
// Write them back
|
||||
//
|
||||
IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0S, Gpe0Sts);
|
||||
IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS, SmiSts);
|
||||
}
|
||||
|
||||
/** Send DRAM Ready opcode.
|
||||
|
||||
@param[in] OpcodeParam Parameter to DRAM ready opcode.
|
||||
|
||||
@retval VOID
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCSendOpcodeDramReady (
|
||||
IN UINT32 OpcodeParam
|
||||
)
|
||||
{
|
||||
|
||||
//
|
||||
// Before sending DRAM ready place invalid value in Scrub Config.
|
||||
//
|
||||
QNCPortWrite (
|
||||
QUARK_NC_RMU_SB_PORT_ID,
|
||||
QUARK_NC_ECC_SCRUB_CONFIG_REG,
|
||||
SCRUB_CFG_INVALID
|
||||
);
|
||||
|
||||
//
|
||||
// Send opcode and use param to notify HW of new RMU firmware location.
|
||||
//
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = OpcodeParam;
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_SHADOW_DW (QUARK_NC_RMU_SB_PORT_ID, 0);
|
||||
|
||||
//
|
||||
// HW completed tasks on DRAM ready when scrub config read back as zero.
|
||||
//
|
||||
while (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_ECC_SCRUB_CONFIG_REG) != 0) {
|
||||
MicroSecondDelay (10);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Relocate RMU Main binary to memory after MRC to improve performance.
|
||||
|
||||
@param[in] DestBaseAddress - Specify the new memory address for the RMU Main binary.
|
||||
@param[in] SrcBaseAddress - Specify the current memory address for the RMU Main binary.
|
||||
@param[in] Size - Specify size of the RMU Main binary.
|
||||
|
||||
@retval VOID
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
RmuMainRelocation (
|
||||
IN CONST UINT32 DestBaseAddress,
|
||||
IN CONST UINT32 SrcBaseAddress,
|
||||
IN CONST UINTN Size
|
||||
)
|
||||
{
|
||||
//
|
||||
// Shadow RMU Main binary into main memory.
|
||||
//
|
||||
CopyMem ((VOID *)(UINTN)DestBaseAddress,(VOID *)(UINTN) SrcBaseAddress, Size);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the total memory size
|
||||
|
||||
**/
|
||||
UINT32
|
||||
EFIAPI
|
||||
QNCGetTotalMemorysize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_HMBOUND_REG) & HMBOUND_MASK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Get the memory range of TSEG.
|
||||
The TSEG's memory is below TOLM.
|
||||
|
||||
@param[out] BaseAddress The base address of TSEG's memory range
|
||||
@param[out] MemorySize The size of TSEG's memory range
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCGetTSEGMemoryRange (
|
||||
OUT UINT64 *BaseAddress,
|
||||
OUT UINT64 *MemorySize
|
||||
)
|
||||
{
|
||||
UINT64 Register = 0;
|
||||
UINT64 SMMAddress = 0;
|
||||
|
||||
Register = QncHsmmcRead ();
|
||||
|
||||
//
|
||||
// Get the SMRAM Base address
|
||||
//
|
||||
SMMAddress = Register & SMM_START_MASK;
|
||||
*BaseAddress = LShift16 (SMMAddress);
|
||||
|
||||
//
|
||||
// Get the SMRAM size
|
||||
//
|
||||
SMMAddress = ((Register & SMM_END_MASK) | (~SMM_END_MASK)) + 1;
|
||||
*MemorySize = SMMAddress - (*BaseAddress);
|
||||
|
||||
DEBUG ((
|
||||
EFI_D_INFO,
|
||||
"TSEG's memory range: BaseAddress = 0x%x, Size = 0x%x\n",
|
||||
(UINT32)*BaseAddress,
|
||||
(UINT32)*MemorySize
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
Updates the PAM registers in the MCH for the requested range and mode.
|
||||
|
||||
@param Start The start address of the memory region
|
||||
@param Length The length, in bytes, of the memory region
|
||||
@param ReadEnable Pointer to the boolean variable on whether to enable read for legacy memory section.
|
||||
If NULL, then read attribute will not be touched by this call.
|
||||
@param ReadEnable Pointer to the boolean variable on whether to enable write for legacy memory section.
|
||||
If NULL, then write attribute will not be touched by this call.
|
||||
@param Granularity A pointer to granularity, in bytes, that the PAM registers support
|
||||
|
||||
@retval RETURN_SUCCESS The PAM registers in the MCH were updated
|
||||
@retval RETURN_INVALID_PARAMETER The memory range is not valid in legacy region.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
QNCLegacyRegionManipulation (
|
||||
IN UINT32 Start,
|
||||
IN UINT32 Length,
|
||||
IN BOOLEAN *ReadEnable,
|
||||
IN BOOLEAN *WriteEnable,
|
||||
OUT UINT32 *Granularity
|
||||
)
|
||||
{
|
||||
//
|
||||
// Do nothing cos no such support on QNC
|
||||
//
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Determine if QNC is supported.
|
||||
|
||||
@retval FALSE QNC is not supported.
|
||||
@retval TRUE QNC is supported.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsQncSupported (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT16 SocVendorId;
|
||||
UINT16 SocDeviceId;
|
||||
|
||||
SocVendorId = MmioRead16 (
|
||||
PciDeviceMmBase (MC_BUS,
|
||||
MC_DEV,
|
||||
MC_FUN) + PCI_VENDOR_ID_OFFSET
|
||||
);
|
||||
|
||||
SocDeviceId = QncGetSocDeviceId();
|
||||
|
||||
//
|
||||
// Verify that this is a supported chipset
|
||||
//
|
||||
if ((SocVendorId != QUARK_MC_VENDOR_ID) || ((SocDeviceId != QUARK_MC_DEVICE_ID) && (SocDeviceId != QUARK2_MC_DEVICE_ID))) {
|
||||
DEBUG ((DEBUG_ERROR, "QNC code doesn't support the Soc VendorId:0x%04x Soc DeviceId:0x%04x!\n", SocVendorId, SocDeviceId));
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Get the DeviceId of the SoC
|
||||
|
||||
@retval PCI DeviceId of the SoC
|
||||
**/
|
||||
UINT16
|
||||
EFIAPI
|
||||
QncGetSocDeviceId (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT16 SocDeviceId;
|
||||
|
||||
SocDeviceId = MmioRead16 (
|
||||
PciDeviceMmBase (
|
||||
MC_BUS,
|
||||
MC_DEV,
|
||||
MC_FUN
|
||||
) + PCI_DEVICE_ID_OFFSET
|
||||
);
|
||||
|
||||
return SocDeviceId;
|
||||
}
|
||||
|
||||
/**
|
||||
Enable SMI detection of legacy flash access violations.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QncEnableLegacyFlashAccessViolationSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 BcValue;
|
||||
|
||||
BcValue = LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL);
|
||||
|
||||
//
|
||||
// Clear BIOSWE & set BLE.
|
||||
//
|
||||
BcValue &= (~B_QNC_LPC_BIOS_CNTL_BIOSWE);
|
||||
BcValue |= (B_QNC_LPC_BIOS_CNTL_BLE);
|
||||
|
||||
LpcPciCfg32 (R_QNC_LPC_BIOS_CNTL) = BcValue;
|
||||
|
||||
DEBUG ((EFI_D_INFO, "BIOS Control Lock Enabled!\n"));
|
||||
}
|
||||
|
||||
/**
|
||||
Setup RMU Thermal sensor registers for Vref mode.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCThermalSensorSetVRefMode (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Tscgf1Config;
|
||||
UINT32 Tscgf2Config;
|
||||
UINT32 Tscgf2Config2;
|
||||
|
||||
Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);
|
||||
Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);
|
||||
Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_VREF_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_VREF_MODE << B_TSCGF1_CONFIG_IBGEN_BP);
|
||||
|
||||
Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);
|
||||
Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_VREF_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);
|
||||
|
||||
Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);
|
||||
Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_VREF_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);
|
||||
|
||||
Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);
|
||||
Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_VREF_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);
|
||||
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);
|
||||
}
|
||||
|
||||
/**
|
||||
Setup RMU Thermal sensor registers for Ratiometric mode.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCThermalSensorSetRatiometricMode (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Tscgf1Config;
|
||||
UINT32 Tscgf2Config;
|
||||
UINT32 Tscgf2Config2;
|
||||
UINT32 Tscgf3Config;
|
||||
|
||||
Tscgf1Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG);
|
||||
Tscgf2Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG);
|
||||
Tscgf2Config2 = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2);
|
||||
Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCURRENTSEL_MASK);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCURRENTSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCURRENTSEL_BP);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSCHOPSEL_MASK);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSCHOPSEL_RATIO_MODE << B_TSCGF1_CONFIG_ISNSCHOPSEL_BP);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_ISNSINTERNALVREFEN);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_ISNSINTERNALVREFEN_RATIO_MODE << B_TSCGF1_CONFIG_ISNSINTERNALVREFEN_BP);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGEN);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_IBGEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGEN_BP);
|
||||
|
||||
Tscgf1Config &= ~(B_TSCGF1_CONFIG_IBGCHOPEN);
|
||||
Tscgf1Config |= (V_TSCGF1_CONFIG_IBGCHOPEN_RATIO_MODE << B_TSCGF1_CONFIG_IBGCHOPEN_BP);
|
||||
|
||||
Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCONFIGSEL_MASK);
|
||||
Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCONFIGSEL_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCONFIGSEL_BP);
|
||||
|
||||
Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ISPARECTRL_MASK);
|
||||
Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ISPARECTRL_RATIO_MODE << B_TSCGF2_CONFIG2_ISPARECTRL_BP);
|
||||
|
||||
Tscgf2Config2 &= ~(B_TSCGF2_CONFIG2_ICALCOARSETUNE_MASK);
|
||||
Tscgf2Config2 |= (V_TSCGF2_CONFIG2_ICALCOARSETUNE_RATIO_MODE << B_TSCGF2_CONFIG2_ICALCOARSETUNE_BP);
|
||||
|
||||
Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSCONTROL_MASK);
|
||||
Tscgf2Config |= (V_TSCGF2_CONFIG_IDSCONTROL_RATIO_MODE << B_TSCGF2_CONFIG_IDSCONTROL_BP);
|
||||
|
||||
Tscgf2Config &= ~(B_TSCGF2_CONFIG_IDSTIMING_MASK);
|
||||
Tscgf2Config |= (V_TSCGF2_CONFIG_IDSTIMING_RATIO_MODE << B_TSCGF2_CONFIG_IDSTIMING_BP);
|
||||
|
||||
Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSGAMMACOEFF_MASK);
|
||||
Tscgf3Config |= (V_TSCGF3_CONFIG_ITSGAMMACOEFF_RATIO_MODE << B_TSCGF3_CONFIG_ITSGAMMACOEFF_BP);
|
||||
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF1_CONFIG, Tscgf1Config);
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG, Tscgf2Config);
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF2_CONFIG2, Tscgf2Config2);
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);
|
||||
}
|
||||
|
||||
/**
|
||||
Setup RMU Thermal sensor trip point values.
|
||||
|
||||
@param[in] CatastrophicTripOnDegreesCelsius - Catastrophic set trip point threshold.
|
||||
@param[in] HotTripOnDegreesCelsius - Hot set trip point threshold.
|
||||
@param[in] HotTripOffDegreesCelsius - Hot clear trip point threshold.
|
||||
|
||||
@retval EFI_SUCCESS Trip points setup.
|
||||
@retval EFI_INVALID_PARAMETER Invalid trip point value.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
QNCThermalSensorSetTripValues (
|
||||
IN CONST UINTN CatastrophicTripOnDegreesCelsius,
|
||||
IN CONST UINTN HotTripOnDegreesCelsius,
|
||||
IN CONST UINTN HotTripOffDegreesCelsius
|
||||
)
|
||||
{
|
||||
UINT32 RegisterValue;
|
||||
|
||||
//
|
||||
// Register fields are 8-bit temperature values of granularity 1 degree C
|
||||
// where 0x00 corresponds to -50 degrees C
|
||||
// and 0xFF corresponds to 205 degrees C.
|
||||
//
|
||||
// User passes unsigned values in degrees Celsius so trips < 0 not supported.
|
||||
//
|
||||
// Add 50 to user values to get values for register fields.
|
||||
//
|
||||
|
||||
if ((CatastrophicTripOnDegreesCelsius > 205) || (HotTripOnDegreesCelsius > 205) || (HotTripOffDegreesCelsius > 205)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// Set new values.
|
||||
//
|
||||
RegisterValue =
|
||||
((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP) | // Cat Trip Clear value must be less than Cat Trip Set Value.
|
||||
((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP) |
|
||||
((HotTripOnDegreesCelsius + 50) << TS_HOT_TRIP_SET_THOLD_BP) |
|
||||
((HotTripOffDegreesCelsius + 50) << TS_HOT_TRIP_CLEAR_THOLD_BP)
|
||||
;
|
||||
|
||||
QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, RegisterValue);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Enable RMU Thermal sensor with a Catastrophic Trip point.
|
||||
|
||||
@retval EFI_SUCCESS Trip points setup.
|
||||
@retval EFI_INVALID_PARAMETER Invalid trip point value.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
QNCThermalSensorEnableWithCatastrophicTrip (
|
||||
IN CONST UINTN CatastrophicTripOnDegreesCelsius
|
||||
)
|
||||
{
|
||||
UINT32 Tscgf3Config;
|
||||
UINT32 TsModeReg;
|
||||
UINT32 TsTripReg;
|
||||
|
||||
//
|
||||
// Trip Register fields are 8-bit temperature values of granularity 1 degree C
|
||||
// where 0x00 corresponds to -50 degrees C
|
||||
// and 0xFF corresponds to 205 degrees C.
|
||||
//
|
||||
// User passes unsigned values in degrees Celsius so trips < 0 not supported.
|
||||
//
|
||||
// Add 50 to user values to get values for register fields.
|
||||
//
|
||||
|
||||
if (CatastrophicTripOnDegreesCelsius > 205) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Tscgf3Config = QNCAltPortRead (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG);
|
||||
TsModeReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE);
|
||||
TsTripReg = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP);
|
||||
|
||||
//
|
||||
// Setup Catastrophic Trip point.
|
||||
//
|
||||
TsTripReg &= ~(TS_CAT_TRIP_SET_THOLD_MASK);
|
||||
TsTripReg |= ((CatastrophicTripOnDegreesCelsius + 50) << TS_CAT_TRIP_SET_THOLD_BP);
|
||||
TsTripReg &= ~(TS_CAT_TRIP_CLEAR_THOLD_MASK);
|
||||
TsTripReg |= ((0 + 50) << TS_CAT_TRIP_CLEAR_THOLD_BP); // Cat Trip Clear value must be less than Cat Trip Set Value.
|
||||
QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_TRIP, TsTripReg);
|
||||
|
||||
//
|
||||
// To enable the TS do the following:
|
||||
// 1) Take the TS out of reset by setting itsrst to 0x0.
|
||||
// 2) Enable the TS using RMU Thermal sensor mode register.
|
||||
//
|
||||
|
||||
Tscgf3Config &= ~(B_TSCGF3_CONFIG_ITSRST);
|
||||
TsModeReg |= TS_ENABLE;
|
||||
|
||||
QNCAltPortWrite (QUARK_SCSS_SOC_UNIT_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_TSCGF3_CONFIG, Tscgf3Config);
|
||||
QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_TS_MODE, TsModeReg);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Lock all RMU Thermal sensor control & trip point registers.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCThermalSensorLockAllRegisters (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 RegValue;
|
||||
UINT32 LockMask;
|
||||
|
||||
LockMask = TS_LOCK_THRM_CTRL_REGS_ENABLE | TS_LOCK_AUX_TRIP_PT_REGS_ENABLE;
|
||||
|
||||
RegValue = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG);
|
||||
RegValue |= LockMask;
|
||||
QNCPortWrite (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG, RegValue);
|
||||
|
||||
ASSERT ((LockMask == (QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_CONFIG) & LockMask)));
|
||||
}
|
||||
|
||||
/**
|
||||
Set chipset policy for double bit ECC error.
|
||||
|
||||
@param[in] PolicyValue Policy to config on double bit ECC error.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCPolicyDblEccBitErr (
|
||||
IN CONST UINT32 PolicyValue
|
||||
)
|
||||
{
|
||||
UINT32 Register;
|
||||
Register = QNCPortRead (QUARK_NC_RMU_SB_PORT_ID, QUARK_NC_RMU_REG_WDT_CONTROL);
|
||||
Register &= ~(B_WDT_CONTROL_DBL_ECC_BIT_ERR_MASK);
|
||||
Register |= PolicyValue;
|
||||
QNCPortWrite (
|
||||
QUARK_NC_RMU_SB_PORT_ID,
|
||||
QUARK_NC_RMU_REG_WDT_CONTROL,
|
||||
Register
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Determine if running on secure Quark hardware Sku.
|
||||
|
||||
@retval FALSE Base Quark Sku or unprovisioned Secure Sku running.
|
||||
@retval TRUE Provisioned SecureSku hardware running.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
QncIsSecureProvisionedSku (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Read QUARK Secure SKU Fuse
|
||||
return ((QNCAltPortRead (QUARK_SCSS_FUSE_SB_PORT_ID, QUARK_SCSS_SOC_UNIT_SPI_ROM_FUSE) & BIT6) == BIT6);
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
## @file
|
||||
# Intel QNC Library Instance
|
||||
#
|
||||
# Intel QNC Library Instance
|
||||
#
|
||||
# Copyright (c) 2013-2015 Intel Corporation.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = IntelQNCLib
|
||||
FILE_GUID = F5B2EA6C-8148-4a4e-88EA-38A4A51F389F
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = IntelQNCLib
|
||||
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
PciExpress.c
|
||||
IntelQNCLib.c
|
||||
CommonHeader.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
TimerLib
|
||||
DebugLib
|
||||
PcdLib
|
||||
PciLib
|
||||
IoLib
|
||||
PciCf8Lib
|
||||
BaseLib
|
||||
CpuLib
|
||||
QNCAccessLib
|
||||
|
||||
[Pcd]
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdPmbaIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdWdtbaIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdRcbaMmioBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdDeviceEnables
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdPcieRootPortConfiguration
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
|
949
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c
Normal file
949
QuarkSocPkg/QuarkNorthCluster/Library/IntelQNCLib/PciExpress.c
Normal file
@@ -0,0 +1,949 @@
|
||||
/** @file
|
||||
QNC PCI Express initialization entry
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "CommonHeader.h"
|
||||
|
||||
#define PCIEXP_ROOT_PORT_URE_ENABLE BIT0 // unsupported request reporting enable
|
||||
#define PCIEXP_ROOT_PORT_FEE_ENABLE BIT1 // Fatal Error Reporting Enable
|
||||
#define PCIEXP_ROOT_PORT_NFE_ENABLE BIT2 // Non-Fatal Error Reporting Enable
|
||||
#define PCIEXP_ROOT_PORT_CEE_ENABLE BIT3 // Correctable Error Reporting Enable
|
||||
#define PCIEXP_ROOT_PORT_SFE_ENABLE BIT4 // System Error on Fatal Error Enable
|
||||
#define PCIEXP_ROOT_PORT_SNE_ENABLE BIT5 // System Error on Non-Fatal Error Enable
|
||||
#define PCIEXP_ROOT_PORT_SCE_ENABLE BIT6 // System Error on Correctable Error Enable
|
||||
|
||||
EFI_STATUS
|
||||
PcieStall (
|
||||
IN UINTN Microseconds
|
||||
)
|
||||
{
|
||||
MicroSecondDelay (Microseconds);
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Find the Offset to a given Capabilities ID
|
||||
CAPID list:
|
||||
0x01 = PCI Power Management Interface
|
||||
0x04 = Slot Identification
|
||||
0x05 = MSI Capability
|
||||
0x10 = PCI Express Capability
|
||||
|
||||
@param[in] Bus Bus number of the interested device
|
||||
@param[in] Device Device number of the interested device
|
||||
@param[in] Function Function number of the interested device
|
||||
@param[in] CapId Capability ID to be scanned
|
||||
|
||||
@retval Offset of desired CAPID
|
||||
|
||||
**/
|
||||
UINT32
|
||||
PcieFindCapId (
|
||||
UINT8 Bus,
|
||||
UINT8 Device,
|
||||
UINT8 Function,
|
||||
UINT8 CapId
|
||||
)
|
||||
{
|
||||
UINT8 CapHeader;
|
||||
|
||||
//
|
||||
// Always start at Offset 0x34
|
||||
//
|
||||
CapHeader = QNCMmPci8 (0, Bus, Device, Function, R_QNC_PCIE_CAP_PTR);
|
||||
|
||||
if (CapHeader == 0xFF) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (CapHeader != 0) {
|
||||
if (QNCMmPci8 (0, Bus, Device, Function, CapHeader) == CapId) {
|
||||
return CapHeader;
|
||||
}
|
||||
CapHeader = QNCMmPci8 (0, Bus, Device, Function, CapHeader + 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Search and return the offset of desired Pci Express Capability ID
|
||||
CAPID list:
|
||||
0x0001 = Advanced Error Rreporting Capability
|
||||
0x0002 = Virtual Channel Capability
|
||||
0x0003 = Device Serial Number Capability
|
||||
0x0004 = Power Budgeting Capability
|
||||
|
||||
@param[in] Bus Bus number of the interested device
|
||||
@param[in] Device Device number of the interested device
|
||||
@param[in] Function Function number of the interested device
|
||||
@param[in] CapId Capability ID to be scanned
|
||||
|
||||
@retval Offset of desired CAPID
|
||||
|
||||
**/
|
||||
UINT32
|
||||
PcieFindExtendedCapId (
|
||||
UINT8 Bus,
|
||||
UINT8 Device,
|
||||
UINT8 Function,
|
||||
UINT16 CapId
|
||||
)
|
||||
{
|
||||
UINT16 CapHeaderOffset;
|
||||
UINT16 CapHeaderId;
|
||||
|
||||
// Start to search at Offset 0x100
|
||||
// Get Capability Header
|
||||
CapHeaderId = 0;
|
||||
CapHeaderOffset = PCIE_CAP_EXT_HEARDER_OFFSET;
|
||||
|
||||
while (CapHeaderOffset != 0 && CapHeaderId != 0xFFFF) {
|
||||
CapHeaderId = QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset);
|
||||
if (CapHeaderId == CapId) {
|
||||
return CapHeaderOffset;
|
||||
}
|
||||
CapHeaderOffset = (QNCMmPci16 (0, Bus, Device, Function, CapHeaderOffset + 2) >> 4);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Map Vc on both root port and downstream device
|
||||
|
||||
@param[in] Bus1 Bus number of the root port
|
||||
@param[in] Device1 Device number of the root port
|
||||
@param[in] Function1 Function number of the root port
|
||||
@param[in] Bus2 Bus number of the downstream device
|
||||
@param[in] Device2 Device number of the downstream device
|
||||
@param[in] Function2 Function number of the downstream device
|
||||
|
||||
@retval EFI_SUCCESS Map Vc successful
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PcieInitTcxVc0 (
|
||||
IN UINT8 Bus1,
|
||||
IN UINT8 Device1,
|
||||
IN UINT8 Function1,
|
||||
IN UINT8 Bus2,
|
||||
IN UINT8 Device2,
|
||||
IN UINT8 Function2
|
||||
)
|
||||
{
|
||||
UINT32 Offset;
|
||||
|
||||
//
|
||||
// Initialize TCx-VC0 value on the port to only use TC0
|
||||
//
|
||||
Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);
|
||||
if (Offset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
QNCMmPci8AndThenOr (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);
|
||||
|
||||
// Set TCx-VC0 value on the Endpoint
|
||||
|
||||
Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);
|
||||
if (Offset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
QNCMmPci8AndThenOr (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET), ~0xF, 1);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Map Traffic Class x to Vc0 on both root port and downstream device
|
||||
|
||||
@param[in] Bus1 Bus number of the root port
|
||||
@param[in] Device1 Device number of the root port
|
||||
@param[in] Function1 Function number of the root port
|
||||
@param[in] Bus2 Bus number of the downstream device
|
||||
@param[in] Device2 Device number of the downstream device
|
||||
@param[in] Function2 Function number of the downstream device
|
||||
@param[in] TCx Traffic Class to be mapped to vc0
|
||||
|
||||
@retval EFI_SUCCESS Map Tcx to Vc0 successful
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PcieMapTcxVc0 (
|
||||
IN UINT8 Bus1,
|
||||
IN UINT8 Device1,
|
||||
IN UINT8 Function1,
|
||||
IN UINT8 Bus2,
|
||||
IN UINT8 Device2,
|
||||
IN UINT8 Function2,
|
||||
IN UINT8 TCx
|
||||
)
|
||||
{
|
||||
UINT32 Offset;
|
||||
|
||||
//
|
||||
// Set TCx-VC0 value on the port
|
||||
//
|
||||
|
||||
Offset = PcieFindExtendedCapId (Bus1, Device1, Function1, 2);
|
||||
if (Offset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
QNCMmPci8 (0, Bus1, Device1, Function1, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);
|
||||
|
||||
// Set TCx-VC0 value on the Endpoint
|
||||
|
||||
Offset = PcieFindExtendedCapId (Bus2, Device2, Function2, 2);
|
||||
if (Offset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
QNCMmPci8 (0, Bus2, Device2, Function2, (Offset + PCIE_SLOT_CAP_OFFSET)) = (UINT8)(1 << TCx);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Set common clock for both root port and downstream device.
|
||||
|
||||
@param[in] Bus1 Bus number of the root port
|
||||
@param[in] Device1 Device number of the root port
|
||||
@param[in] Function1 Function number of the root port
|
||||
@param[in] Bus2 Device number of the downstream device
|
||||
@param[in] Device2 Function number of the downstream device
|
||||
|
||||
@retval EFI_SUCCESS Set common clock successful
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PcieSetCommonClock (
|
||||
IN UINT8 Bus1,
|
||||
IN UINT8 Device1,
|
||||
IN UINT8 Function1,
|
||||
IN UINT8 Bus2,
|
||||
IN UINT8 Device2
|
||||
)
|
||||
{
|
||||
UINT32 CapOffset1;
|
||||
UINT32 CapOffset2;
|
||||
UINT8 Function2;
|
||||
UINT8 CommonClock;
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Get the pointer to the Port PCI Express Capability Structure.
|
||||
//
|
||||
CommonClock = 0;
|
||||
CapOffset1 = PcieFindCapId (Bus1, Device1, Function1, PCIE_CAPID);
|
||||
if (CapOffset1 == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Step 1
|
||||
// Read the Slot Clock Configuration bit of the Link status register of the root port and the endpoint device connected to the port
|
||||
// If both components have this bit set to 1, then System BIOS should set the "Common Clock Configuration" bit in the Link Control Registers
|
||||
// for both components at both sides of the link to indicate that components at both ends
|
||||
// of the link use a common clock source
|
||||
//
|
||||
|
||||
//
|
||||
// Check the Port Slot Clock Configuration Bit.
|
||||
//
|
||||
if ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
for (Function2 = 0; Function2 < 8; Function2++) {
|
||||
//
|
||||
// Check the Endpoint Slot Clock Configuration Bit.
|
||||
//
|
||||
CapOffset2 = PcieFindCapId (Bus2, Device2, Function2, PCIE_CAPID);
|
||||
if ((CapOffset2 != 0) &&
|
||||
((QNCMmPci16 (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_SCC) != 0)) {
|
||||
|
||||
//
|
||||
// Common clock is supported, set common clock bit on root port
|
||||
// and the endpoint
|
||||
//
|
||||
if (CommonClock == 0) {
|
||||
QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);
|
||||
CommonClock++;
|
||||
}
|
||||
QNCMmPci8Or (0, Bus2, Device2, Function2, (CapOffset2 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_CCC);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Step 2 If the Common Clock Configuration bit was changed by BIOS in step 1,
|
||||
// System BIOS should initiate a link training by setting the Retrain Link bit
|
||||
// in the Link Control register of the root port (D28:F0/F1 offset
|
||||
// 50h [5]) to "1b" and then poll the Link Training bit in the Link Status
|
||||
// register of the root port (D28:F0/F1/F2/F3/F4/F5 offset 52h [11]) until it is
|
||||
// "0b".
|
||||
//
|
||||
if (CommonClock == 0) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
} else {
|
||||
//
|
||||
// Retrain the Link per PCI Express Specification.
|
||||
//
|
||||
QNCMmPci8Or (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_CNT_OFFSET), B_QNC_PCIE_LCTL_RL);
|
||||
|
||||
//
|
||||
// Wait until Re-Training has completed.
|
||||
//
|
||||
while ((QNCMmPci16 (0, Bus1, Device1, Function1, (CapOffset1 + PCIE_LINK_STS_OFFSET)) & B_QNC_PCIE_LSTS_LT) != 0);
|
||||
Status = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Enables the CLKREQ# PM on all the end point functions
|
||||
|
||||
@param[in] Bus Bus number of the downstream device
|
||||
@param[in] Device Device number of the downstream device
|
||||
|
||||
@retval None
|
||||
|
||||
**/
|
||||
VOID
|
||||
PcieSetClkreq (
|
||||
IN UINT8 Bus,
|
||||
IN UINT8 Device
|
||||
)
|
||||
{
|
||||
UINT8 Function;
|
||||
UINT32 CapOffset;
|
||||
|
||||
//
|
||||
// Parse thro all the functions of the endpoint and find the PCIe Cap ID (offset 10h) and if
|
||||
// exists then enable the CLKREQ# bit (BIT8) on that function
|
||||
//
|
||||
for (Function = 0; Function < 8; Function++) {
|
||||
//
|
||||
// Find the PCIe Cap Id (offset 10h)
|
||||
//
|
||||
CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);
|
||||
if (CapOffset == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if CLKREQ# is supported by the endpoints
|
||||
//
|
||||
if ((QNCMmPci32 (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CAP_OFFSET))
|
||||
& B_QNC_PCIE_LCAP_CPM) != B_QNC_PCIE_LCAP_CPM) {
|
||||
//
|
||||
// CLKREQ# is not supported so dont do anything
|
||||
//
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Now enable the CLKREQ#
|
||||
//
|
||||
for (Function = 0; Function < 8; Function++) {
|
||||
//
|
||||
// Find the PCIe Cap Id (offset 10h)
|
||||
//
|
||||
CapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);
|
||||
if (CapOffset == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
QNCMmPci16Or (0, Bus, Device, Function, (CapOffset + PCIE_LINK_CNT_OFFSET), BIT8);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Configure ASPM automatically for both root port and downstream device.
|
||||
|
||||
@param[in] RootBus Bus number of the root port
|
||||
@param[in] RootDevice Device number of the root port
|
||||
@param[in] RootFunction Function number of the root port
|
||||
@param[in] EndpointBus Bus number of the downstream device
|
||||
@param[in] EndpointDevice Device number of the downstream device
|
||||
@param[in] EndpointFunction Function number of the downstream device
|
||||
@param[in] LinkAspmVal Currently used ASPM setting
|
||||
|
||||
@retval EFI_SUCCESS Configure ASPM successful
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PcieSetAspmAuto (
|
||||
IN UINT8 RootBus,
|
||||
IN UINT8 RootDevice,
|
||||
IN UINT8 RootFunction,
|
||||
IN UINT8 EndpointBus,
|
||||
IN UINT8 EndpointDevice,
|
||||
IN UINT8 EndpointFunction,
|
||||
OUT UINT16 *LinkAspmVal
|
||||
)
|
||||
{
|
||||
UINT32 RootPcieCapOffset;
|
||||
UINT32 EndpointPcieCapOffset;
|
||||
UINT16 RootPortAspm;
|
||||
UINT16 EndPointAspm;
|
||||
UINT16 EndPointVendorId;
|
||||
UINT16 EndPointDeviceId;
|
||||
UINT8 EndPointRevId;
|
||||
UINT16 AspmVal;
|
||||
UINT32 PortLxLat;
|
||||
UINT32 EndPointLxLat;
|
||||
UINT32 LxLat;
|
||||
|
||||
//
|
||||
// Get the pointer to the Port PCI Express Capability Structure.
|
||||
//
|
||||
RootPcieCapOffset = PcieFindCapId (RootBus, RootDevice, RootFunction, PCIE_CAPID);
|
||||
if (RootPcieCapOffset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Get the pointer to the Endpoint PCI Express Capability Structure.
|
||||
//
|
||||
EndpointPcieCapOffset = PcieFindCapId (EndpointBus, EndpointDevice, EndpointFunction, PCIE_CAPID);
|
||||
if (EndpointPcieCapOffset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Obtain initial ASPM settings from respective port capability registers.
|
||||
//
|
||||
RootPortAspm = (QNCMmPci16 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;
|
||||
|
||||
//
|
||||
// Configure downstream device if present.
|
||||
//
|
||||
EndPointAspm = (QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;
|
||||
|
||||
//
|
||||
// Mask APMC with values from lookup table.
|
||||
// RevID of 0xFF applies to all steppings.
|
||||
//
|
||||
|
||||
EndPointVendorId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 0);
|
||||
EndPointDeviceId = QNCMmPci16 (0, EndpointBus, EndpointDevice, EndpointFunction, 2);
|
||||
EndPointRevId = QNCMmPci8 (0, EndpointBus, EndpointDevice, EndpointFunction, 8);
|
||||
|
||||
// TODO: Mask with latency/acceptable latency comparison results.
|
||||
|
||||
AspmVal = RootPortAspm;
|
||||
if (RootPortAspm > EndPointAspm) {
|
||||
AspmVal = EndPointAspm;
|
||||
}
|
||||
|
||||
//
|
||||
// Check if L1 should be enabled based on port and endpoint L1 exit latency.
|
||||
//
|
||||
if(AspmVal & BIT1) {
|
||||
PortLxLat = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;
|
||||
EndPointLxLat = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL1_MASK;
|
||||
|
||||
LxLat = PortLxLat;
|
||||
if(PortLxLat < EndPointLxLat) {
|
||||
LxLat = EndPointLxLat;
|
||||
}
|
||||
|
||||
//
|
||||
// check if the value is bigger than endpoint L1 acceptable exit latency, if it is
|
||||
// larger than accepted value, then we should disable L1
|
||||
//
|
||||
LxLat >>= 6;
|
||||
if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E1AL)) {
|
||||
AspmVal &= ~BIT1;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check if L0s should be enabled based on port and endpoint L0s exit latency.
|
||||
//
|
||||
if(AspmVal & BIT0) {
|
||||
PortLxLat = QNCMmPci32 (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset+ PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;
|
||||
EndPointLxLat = QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_EL0_MASK;
|
||||
|
||||
LxLat = PortLxLat;
|
||||
if(PortLxLat < EndPointLxLat) {
|
||||
LxLat = EndPointLxLat;
|
||||
}
|
||||
|
||||
//
|
||||
// check if the value is bigger than endpoint L0s acceptable exit latency, if it is
|
||||
// larger than accepted value, then we should disable L0s
|
||||
//
|
||||
LxLat >>= 6;
|
||||
if(LxLat > (QNCMmPci32 (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_DEV_CAP_OFFSET)) & B_QNC_PCIE_DCAP_E0AL)) {
|
||||
AspmVal &= ~BIT0;
|
||||
}
|
||||
}
|
||||
|
||||
RootPortAspm = AspmVal;
|
||||
|
||||
*LinkAspmVal = AspmVal;
|
||||
//
|
||||
// Set Endpoint Aspm
|
||||
//
|
||||
QNCMmPci16AndThenOr (0, EndpointBus, EndpointDevice, EndpointFunction, (EndpointPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, AspmVal);
|
||||
|
||||
|
||||
//
|
||||
// Set Root Port Aspm
|
||||
//
|
||||
QNCMmPci16AndThenOr (0, RootBus, RootDevice, RootFunction, (RootPcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, RootPortAspm);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Configure ASPM based on the given setting for the interested device.
|
||||
|
||||
@param[in] Bus Bus number of the interested device
|
||||
@param[in] Device Device number of the interested device
|
||||
@param[in] Function Function number of the interested device
|
||||
@param[in] AspmSetting Aspm setting
|
||||
@param[in] LinkAspmVal Currently used ASPM setting
|
||||
|
||||
@retval EFI_SUCCESS Configure ASPM successful
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
PcieSetAspmManual (
|
||||
IN UINT8 Bus,
|
||||
IN UINT8 Device,
|
||||
IN UINT8 Function,
|
||||
IN UINT8 AspmSetting,
|
||||
OUT UINT16 *LinkAspmVal
|
||||
)
|
||||
{
|
||||
UINT32 PcieCapOffset;
|
||||
UINT16 PortAspm;
|
||||
|
||||
//
|
||||
// Get the pointer to the Port PCI Express Capability Structure.
|
||||
//
|
||||
PcieCapOffset = PcieFindCapId (Bus, Device, Function, PCIE_CAPID);
|
||||
if (PcieCapOffset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
// Read the Link Capability register's ASPM setting
|
||||
PortAspm = (QNCMmPci16 (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CAP_OFFSET)) & B_QNC_PCIE_LCAP_APMS_MASK) >> V_QNC_PCIE_LCAP_APMS_OFFSET;
|
||||
// Mask it with the Setup selection
|
||||
PortAspm &= AspmSetting;
|
||||
|
||||
*LinkAspmVal = PortAspm;
|
||||
// Write it to the Link Control register
|
||||
QNCMmPci16AndThenOr (0, Bus, Device, Function, (PcieCapOffset + PCIE_LINK_CNT_OFFSET), 0xFFFC, PortAspm);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Perform Initialization on one PCI Express root port.
|
||||
|
||||
@param[in] RootPortIndex Index of PCI Express root port
|
||||
@param[in] RootPortConfig Pointer to the given pcie root port configuration
|
||||
@param[in] PciExpressBar Base address of pcie space
|
||||
@param[in] QNCRootComplexBar Base address of root complex
|
||||
@param[in] QNCPmioBase Base address of PM IO space
|
||||
@param[in] QNCGpeBase Base address of gpe IO space
|
||||
|
||||
@retval EFI_SUCCESS Initialization successful
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
QNCRootPortInit (
|
||||
IN UINT32 RootPortIndex,
|
||||
IN PCIEXP_ROOT_PORT_CONFIGURATION *RootPortConfig,
|
||||
IN UINT64 PciExpressBar,
|
||||
IN UINT32 QNCRootComplexBar,
|
||||
IN UINT32 QNCPmioBase,
|
||||
IN UINT32 QNCGpeBase
|
||||
)
|
||||
{
|
||||
UINT64 RPBase;
|
||||
UINT64 EndPointBase;
|
||||
UINT64 LpcBase;
|
||||
UINT16 AspmVal;
|
||||
UINT16 SlotStatus;
|
||||
UINTN Index;
|
||||
UINT32 CapOffset;
|
||||
UINT32 DwordReg;
|
||||
|
||||
RPBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + ((PCI_DEVICE_NUMBER_PCIE_ROOTPORT) << 3) + ((PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex) << 0)) << 12);
|
||||
LpcBase = PciExpressBar + (((PCI_BUS_NUMBER_QNC << 8) + (31 << 3) + (0 << 0)) << 12);
|
||||
CapOffset = PcieFindCapId (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), PCIE_CAPID);
|
||||
|
||||
if (CapOffset == 0) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize "Slot Implmemented Bit" for this root port
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.SlotImplemented) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_XCAP, B_QNC_PCIE_XCAP_SI);
|
||||
}
|
||||
|
||||
//
|
||||
// For Root Port Slots Numbering on the CRBs.
|
||||
// Root Port 0 = Slot 1
|
||||
// Root Port 1 = Slot 2
|
||||
// Root Port 2 = Slot 3
|
||||
// Root Port 3 = Slot 4
|
||||
//
|
||||
DwordReg = QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP);
|
||||
DwordReg &= B_QNC_PCIE_SLCAP_MASK_RSV_VALUE;
|
||||
DwordReg |= (V_QNC_PCIE_SLCAP_SLV << V_QNC_PCIE_SLCAP_SLV_OFFSET);
|
||||
DwordReg |= ((RootPortConfig[RootPortIndex].Bits.PhysicalSlotNumber) << V_QNC_PCIE_SLCAP_PSN_OFFSET) ;
|
||||
QNCMmio32 (RPBase, R_QNC_PCIE_SLCAP) = DwordReg;
|
||||
|
||||
//
|
||||
// Check for a Presence Detect Change.
|
||||
//
|
||||
SlotStatus = QNCMmio16 (RPBase, R_QNC_PCIE_SLSTS);
|
||||
if ((SlotStatus & (B_QNC_PCIE_SLSTS_PDS + B_QNC_PCIE_SLSTS_PDC)) == 0) {
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
|
||||
//
|
||||
// Temporarily Hardcode the Root Port Bridge Number to 2.
|
||||
//
|
||||
// This Endpoint check should immediately pass. Howerver, a 900ms delay
|
||||
// has been added to match the timing requirements of the PCI Express Base
|
||||
// Specification, Revision 1.0A, Section 6.6 ("...software must allow 1.0s
|
||||
// after a reset of a device, before it may determine that a device which
|
||||
// fails to return a Successful Completion status for a valid Configuration
|
||||
// Request is a broken device"). Note that a 100ms delay was already added
|
||||
// after the Root Ports were first taken out of reset.
|
||||
//
|
||||
QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF, 0x00020200);
|
||||
//
|
||||
// Only do this when a downstream device is present
|
||||
//
|
||||
EndPointBase = PciExpressBar + (((2 << 8) + (0 << 3) + (0 << 0)) << 12);
|
||||
if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {
|
||||
for (Index = 0; Index < V_PCIE_MAX_TRY_TIMES; Index++){
|
||||
if (QNCMmio16 (EndPointBase, 0x0) != 0xFFFF) {
|
||||
break;
|
||||
}
|
||||
PcieStall (15);
|
||||
}
|
||||
if (Index >= V_PCIE_MAX_TRY_TIMES) {
|
||||
//
|
||||
// Clear Bus Numbers.
|
||||
//
|
||||
QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);
|
||||
return EFI_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PCI Express* Virtual Channels
|
||||
// Clear TC1-7 Traffic classes.
|
||||
// Map TC0-VC0
|
||||
//
|
||||
PcieInitTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0);
|
||||
PcieMapTcxVc0 (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, 0x0);
|
||||
|
||||
//
|
||||
// Set Common Clock for inserted cards
|
||||
//
|
||||
if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {
|
||||
PcieSetCommonClock (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Flow for Enabling ASPM
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.AspmEnable) {
|
||||
if (RootPortConfig[RootPortIndex].Bits.AspmAutoEnable) {
|
||||
PcieSetAspmAuto (PCI_BUS_NUMBER_QNC, (UINT8)(PCI_DEVICE_NUMBER_PCIE_ROOTPORT), (UINT8)(PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex), 2, 0, 0, &AspmVal);
|
||||
} else {
|
||||
//
|
||||
// Set ASPM values according to setup selections, masked by capabilities
|
||||
//
|
||||
PcieSetAspmManual (
|
||||
PCI_BUS_NUMBER_QNC,
|
||||
(UINT8) (PCI_DEVICE_NUMBER_PCIE_ROOTPORT),
|
||||
(UINT8) (PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0 + RootPortIndex),
|
||||
(UINT8) ((RootPortConfig[RootPortIndex].Bits.AspmL0sEnable & 0x01) | (RootPortConfig[RootPortIndex].Bits.AspmL1Enable << 1)),
|
||||
&AspmVal
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Enable the PCIe CLKREQ#
|
||||
//
|
||||
if ((SlotStatus & B_QNC_PCIE_SLSTS_PDS) != 0) {
|
||||
PcieSetClkreq (2, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// Clear Bus Numbers
|
||||
//
|
||||
QNCMmio32And (RPBase, R_QNC_PCIE_BNUM, 0xFF0000FF);
|
||||
|
||||
//
|
||||
// Additional configurations
|
||||
//
|
||||
|
||||
//
|
||||
// PCI-E Unsupported Request Reporting Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_URE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_URE);
|
||||
}
|
||||
|
||||
//
|
||||
// Device Fatal Error Reporting Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_FEE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_FEE);
|
||||
}
|
||||
|
||||
//
|
||||
// Device Non Fatal Error Reporting Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_NFE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_NFE);
|
||||
}
|
||||
|
||||
//
|
||||
// Device Correctable Error Reporting Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_CEE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_DCTL, B_QNC_PCIE_DCTL_CEE);
|
||||
}
|
||||
//
|
||||
// Root PCI-E PME Interrupt Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PmeInterruptEnable) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_PIE);
|
||||
}
|
||||
//
|
||||
// Root PCI-E System Error on Fatal Error Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SFE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SFE);
|
||||
}
|
||||
|
||||
//
|
||||
// Root PCI-E System Error on Non-Fatal Error Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SNE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SNE);
|
||||
}
|
||||
|
||||
//
|
||||
// Root PCI-E System Error on Correctable Error Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PortErrorMask & PCIEXP_ROOT_PORT_SCE_ENABLE) {
|
||||
QNCMmio16Or (RPBase, R_QNC_PCIE_RCTL, B_QNC_PCIE_RCTL_SCE);
|
||||
}
|
||||
|
||||
//
|
||||
// Root PCI-E Powermanagement SCI Enabled
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.PmSciEnable) {
|
||||
//
|
||||
// Make sure that PME Interrupt Enable bit of Root Control register
|
||||
// of PCI Express Capability struceture is cleared
|
||||
//
|
||||
QNCMmio32And (RPBase, R_QNC_PCIE_RCTL, (~B_QNC_PCIE_RCTL_PIE));
|
||||
QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_PMME), B_QNC_PCIE_MPC_PMCE);
|
||||
|
||||
//
|
||||
// Make sure GPE0 Stutus RW1C Bit is clear.
|
||||
//
|
||||
DwordReg = IoRead32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S);
|
||||
if ((DwordReg & B_QNC_GPE0BLK_GPE0S_PCIE) != 0) {
|
||||
IoWrite32 (QNCGpeBase + R_QNC_GPE0BLK_GPE0S, B_QNC_GPE0BLK_GPE0S_PCIE);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// PCIe Hot Plug SCI Enable
|
||||
//
|
||||
if (RootPortConfig[RootPortIndex].Bits.HotplugSciEnable) {
|
||||
//
|
||||
// Write clear for :
|
||||
// Attention Button Pressed (bit0)
|
||||
// Presence Detect Changed (bit3)
|
||||
//
|
||||
QNCMmio32Or (RPBase, R_QNC_PCIE_SLSTS, (B_QNC_PCIE_SLSTS_PDC | B_QNC_PCIE_SLSTS_ABP));
|
||||
|
||||
//
|
||||
// Sequence 2: Program the following bits in Slot Control register at offset 18h
|
||||
// of PCI Express* Capability structure:
|
||||
// Attention Button Pressed Enable (bit0) = 1b
|
||||
// Presence Detect Changed Enable (bit3) = 1b
|
||||
// Hot Plug Interrupt Enable (bit5) = 0b
|
||||
//
|
||||
QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_SLCTL, (~B_QNC_PCIE_SLCTL_HPE), (B_QNC_PCIE_SLCTL_PDE | B_QNC_PCIE_SLCTL_ABE));
|
||||
|
||||
//
|
||||
// Sequence 3: Program Misc Port Config (MPC) register at PCI config space offset
|
||||
// D8h as follows:
|
||||
// Hot Plug SCI Enable (HPCE, bit30) = 1b
|
||||
// Hot Plug SMI Enable (HPME, bit1) = 0b
|
||||
//
|
||||
QNCMmio32AndThenOr (RPBase, R_QNC_PCIE_MPC, (~B_QNC_PCIE_MPC_HPME), B_QNC_PCIE_MPC_HPCE);
|
||||
}
|
||||
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Perform Initialization of the Downstream Root Ports
|
||||
**/
|
||||
VOID
|
||||
QNCDownStreamPortsInit (
|
||||
IN PCIEXP_ROOT_PORT_CONFIGURATION *RootPortConfig,
|
||||
IN QNC_DEVICE_ENABLES *QNCDeviceEnables,
|
||||
IN UINT64 PciExpressBar,
|
||||
IN UINT32 QNCRootComplexBar,
|
||||
IN UINT32 QNCPmioBase,
|
||||
IN UINT32 QNCGpeBase,
|
||||
OUT UINTN *RpEnableMask
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINT32 Index;
|
||||
|
||||
//
|
||||
// Initialize every root port and downstream device
|
||||
//
|
||||
for (Index = 0;Index < MAX_PCI_EXPRESS_ROOT_PORTS;Index++) {
|
||||
if ((QNCDeviceEnables->Uint32 & (1 << Index)) != 0) {
|
||||
Status = QNCRootPortInit (
|
||||
Index,
|
||||
RootPortConfig,
|
||||
PciExpressBar,
|
||||
QNCRootComplexBar,
|
||||
QNCPmioBase,
|
||||
QNCGpeBase
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
(*RpEnableMask) |= LShiftU64(1, Index);
|
||||
DEBUG ((EFI_D_INFO, " Root Port %x device found, enabled. RpEnableMask: 0x%x\n", Index + 1, *RpEnableMask));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Do early init of pci express rootports on Soc.
|
||||
|
||||
**/
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
PciExpressEarlyInit (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Setup Message Bus Idle Counter (SBIC) values.
|
||||
//
|
||||
QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);
|
||||
QNCMmPci8(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL) = QNCMmPci8AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_IOSFSBCTL, (~B_QNC_PCIE_IOSFSBCTL_SBIC_MASK), V_PCIE_ROOT_PORT_SBIC_VALUE);
|
||||
|
||||
//
|
||||
// Program SVID/SID the same as VID/DID for Root ports.
|
||||
//
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, PCI_VENDOR_ID_OFFSET);
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_SVID) = QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, PCI_VENDOR_ID_OFFSET);
|
||||
|
||||
//
|
||||
// Set the IPF bit in MCR2
|
||||
//
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2) = QNCMmPci32Or(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_1, R_QNC_PCIE_MPC2, B_QNC_PCIE_MPC2_IPF);
|
||||
|
||||
//
|
||||
// Set up the Posted and Non Posted Request sizes for PCIe
|
||||
//
|
||||
QNCMmPci32(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG) = QNCMmPci32AndThenOr(0, PCI_BUS_NUMBER_QNC, PCI_DEVICE_NUMBER_PCIE_ROOTPORT, PCI_FUNCTION_NUMBER_PCIE_ROOTPORT_0, R_QNC_PCIE_CCFG, ~B_QNC_PCIE_CCFG_UPSD, (B_QNC_PCIE_CCFG_UNRS | B_QNC_PCIE_CCFG_UPRS));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Complete initialization all the pci express rootports on Soc.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
PciExpressInit (
|
||||
)
|
||||
{
|
||||
UINT64 PciExpressBar;
|
||||
UINT32 QNCRootComplexBar;
|
||||
UINT32 QNCGpioBase;
|
||||
UINT32 QNCPmioBase;
|
||||
UINT32 QNCGpeBase;
|
||||
UINTN RpEnableMask;
|
||||
PCIEXP_ROOT_PORT_CONFIGURATION *mRootPortConfig;
|
||||
QNC_DEVICE_ENABLES mQNCDeviceEnables;
|
||||
|
||||
//
|
||||
// Get BAR registers
|
||||
//
|
||||
QNCRootComplexBar = QNC_RCRB_BASE;
|
||||
QNCGpioBase = LpcPciCfg32 (R_QNC_LPC_GBA_BASE) & B_QNC_LPC_GPA_BASE_MASK;
|
||||
QNCPmioBase = LpcPciCfg32 (R_QNC_LPC_PM1BLK) & B_QNC_LPC_PM1BLK_MASK;
|
||||
QNCGpeBase = LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & B_QNC_LPC_GPE0BLK_MASK;
|
||||
RpEnableMask = 0; // assume all root ports are disabled
|
||||
|
||||
PciExpressBar = PcdGet64 (PcdPciExpressBaseAddress);
|
||||
|
||||
//
|
||||
// Get platform information from PCD entries
|
||||
//
|
||||
mQNCDeviceEnables.Uint32 = PcdGet32 (PcdDeviceEnables);
|
||||
mRootPortConfig = (PCIEXP_ROOT_PORT_CONFIGURATION*) PcdGetPtr (PcdPcieRootPortConfiguration);
|
||||
|
||||
DEBUG ((EFI_D_INFO, " mRootPortConfig: 0x%x, value1: 0x%x, value2: 0x%x, value3: 0x%x, value4: 0x%x\n",
|
||||
mRootPortConfig, mRootPortConfig[0].Uint32, mRootPortConfig[1].Uint32,
|
||||
mRootPortConfig[2].Uint32, mRootPortConfig[3].Uint32));
|
||||
|
||||
QNCDownStreamPortsInit (
|
||||
mRootPortConfig,
|
||||
&mQNCDeviceEnables,
|
||||
PciExpressBar,
|
||||
QNCRootComplexBar,
|
||||
QNCPmioBase,
|
||||
QNCGpeBase,
|
||||
&RpEnableMask
|
||||
);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
2117
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.c
Normal file
2117
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.c
Normal file
File diff suppressed because it is too large
Load Diff
48
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.inf
Normal file
48
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.inf
Normal file
@@ -0,0 +1,48 @@
|
||||
## @file
|
||||
# MTRR library provides APIs for MTRR operation.
|
||||
#
|
||||
# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = MtrrLib
|
||||
MODULE_UNI_FILE = MtrrLib.uni
|
||||
FILE_GUID = 6826b408-f4f3-47ee-917f-af7047f9d937
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = MtrrLib
|
||||
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
MtrrLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseMemoryLib
|
||||
BaseLib
|
||||
CpuLib
|
||||
DebugLib
|
||||
QNCAccessLib
|
||||
|
||||
[Pcd]
|
||||
gUefiCpuPkgTokenSpaceGuid.PcdCpuNumberOfReservedVariableMtrrs ## SOMETIMES_CONSUMES
|
||||
|
24
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.uni
Normal file
24
QuarkSocPkg/QuarkNorthCluster/Library/MtrrLib/MtrrLib.uni
Normal file
@@ -0,0 +1,24 @@
|
||||
// /** @file
|
||||
// MtrrLib Module Localized Abstract and Description Content
|
||||
//
|
||||
// Copyright (c) 2012 - 2013, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// This program and the accompanying materials
|
||||
// are licensed and made available under the terms and conditions of the BSD License
|
||||
// which accompanies this distribution. The full text of the license may be found at
|
||||
// http://opensource.org/licenses/bsd-license.php
|
||||
//
|
||||
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT
|
||||
#language en-US
|
||||
"MTRR library provides APIs for MTRR operation"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION
|
||||
#language en-US
|
||||
"MTRR library provides APIs for MTRR operation."
|
||||
|
@@ -0,0 +1,34 @@
|
||||
/** @file
|
||||
Base Lib function for QNC internal network access.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
//
|
||||
// The package level header files this module uses
|
||||
//
|
||||
#include <Uefi.h>
|
||||
|
||||
/**
|
||||
Gets the base address of PCI Express for Quark North Cluster.
|
||||
|
||||
@return The base address of PCI Express for Quark North Cluster.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
QncGetPciExpressBaseAddress (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (UINTN) PcdGet64(PcdPciExpressBaseAddress);
|
||||
}
|
@@ -0,0 +1,333 @@
|
||||
/** @file
|
||||
Common Lib function for QNC internal network access.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
//
|
||||
// The package level header files this module uses
|
||||
//
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <IntelQNCRegs.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <IndustryStandard/Pci22.h>
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
QNCPortRead(
|
||||
UINT8 Port,
|
||||
UINT32 RegAddress
|
||||
)
|
||||
{
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_READ_DW (Port, RegAddress);
|
||||
return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCPortWrite (
|
||||
UINT8 Port,
|
||||
UINT32 RegAddress,
|
||||
UINT32 WriteValue
|
||||
)
|
||||
{
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_WRITE_DW (Port, RegAddress);
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
QNCAltPortRead (
|
||||
UINT8 Port,
|
||||
UINT32 RegAddress
|
||||
)
|
||||
{
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_READ_DW (Port, RegAddress);
|
||||
return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCAltPortWrite (
|
||||
UINT8 Port,
|
||||
UINT32 RegAddress,
|
||||
UINT32 WriteValue
|
||||
)
|
||||
{
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = ALT_MESSAGE_WRITE_DW (Port, RegAddress);
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
QNCPortIORead(
|
||||
UINT8 Port,
|
||||
UINT32 RegAddress
|
||||
)
|
||||
{
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_READ_DW (Port, RegAddress);
|
||||
return McD0PciCfg32 (QNC_ACCESS_PORT_MDR);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCPortIOWrite (
|
||||
UINT8 Port,
|
||||
UINT32 RegAddress,
|
||||
UINT32 WriteValue
|
||||
)
|
||||
{
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MDR) = WriteValue;
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MEA) = (RegAddress & 0xFFFFFF00);
|
||||
McD0PciCfg32 (QNC_ACCESS_PORT_MCR) = MESSAGE_IO_WRITE_DW (Port, RegAddress);
|
||||
}
|
||||
|
||||
RETURN_STATUS
|
||||
EFIAPI
|
||||
QNCMmIoWrite (
|
||||
UINT32 MmIoAddress,
|
||||
QNC_MEM_IO_WIDTH Width,
|
||||
UINT32 DataNumber,
|
||||
VOID *pData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This is for the special consideration for QNC MMIO write, as required by FWG, a reading must be performed after MMIO writing
|
||||
to ensure the expected write is processed and data is flushed into chipset
|
||||
|
||||
Arguments:
|
||||
|
||||
Row -- row number to be cleared ( start from 1 )
|
||||
|
||||
Returns:
|
||||
|
||||
EFI_SUCCESS
|
||||
|
||||
--*/
|
||||
{
|
||||
RETURN_STATUS Status;
|
||||
UINTN Index;
|
||||
|
||||
Status = RETURN_SUCCESS;
|
||||
|
||||
for (Index =0; Index < DataNumber; Index++) {
|
||||
switch (Width) {
|
||||
case QNCMmioWidthUint8:
|
||||
QNCMmio8 (MmIoAddress, 0) = ((UINT8 *)pData)[Index];
|
||||
if (QNCMmio8 (MmIoAddress, 0) != ((UINT8*)pData)[Index]) {
|
||||
Status = RETURN_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case QNCMmioWidthUint16:
|
||||
QNCMmio16 (MmIoAddress, 0) = ((UINT16 *)pData)[Index];
|
||||
if (QNCMmio16 (MmIoAddress, 0) != ((UINT16 *)pData)[Index]) {
|
||||
Status = RETURN_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case QNCMmioWidthUint32:
|
||||
QNCMmio32 (MmIoAddress, 0) = ((UINT32 *)pData)[Index];
|
||||
if (QNCMmio32 (MmIoAddress, 0) != ((UINT32 *)pData)[Index]) {
|
||||
Status = RETURN_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case QNCMmioWidthUint64:
|
||||
QNCMmio64 (MmIoAddress, 0) = ((UINT64 *)pData)[Index];
|
||||
if (QNCMmio64 (MmIoAddress, 0) != ((UINT64 *)pData)[Index]) {
|
||||
Status = RETURN_DEVICE_ERROR;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
UINT32
|
||||
EFIAPI
|
||||
QncHsmmcRead (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QncHsmmcWrite (
|
||||
UINT32 WriteValue
|
||||
)
|
||||
{
|
||||
UINT16 DeviceId;
|
||||
UINT32 Data32;
|
||||
|
||||
//
|
||||
// Check what Soc we are running on (read Host bridge DeviceId)
|
||||
//
|
||||
DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
|
||||
|
||||
if (DeviceId == QUARK2_MC_DEVICE_ID) {
|
||||
//
|
||||
// Disable HSMMC configuration
|
||||
//
|
||||
Data32 = QncHsmmcRead ();
|
||||
Data32 &= ~SMM_CTL_EN;
|
||||
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, Data32);
|
||||
|
||||
//
|
||||
// Validate HSMMC configuration is disabled
|
||||
//
|
||||
Data32 = QncHsmmcRead ();
|
||||
ASSERT((Data32 & SMM_CTL_EN) == 0);
|
||||
|
||||
//
|
||||
// Enable HSMMC configuration
|
||||
//
|
||||
WriteValue |= SMM_CTL_EN;
|
||||
}
|
||||
|
||||
//
|
||||
// Write the register value
|
||||
//
|
||||
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HSMMC, WriteValue);
|
||||
|
||||
if (DeviceId == QUARK2_MC_DEVICE_ID) {
|
||||
//
|
||||
// Validate HSMMC configuration is enabled
|
||||
//
|
||||
Data32 = QncHsmmcRead ();
|
||||
ASSERT((Data32 & SMM_CTL_EN) != 0);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QncImrWrite (
|
||||
UINT32 ImrBaseOffset,
|
||||
UINT32 ImrLow,
|
||||
UINT32 ImrHigh,
|
||||
UINT32 ImrReadMask,
|
||||
UINT32 ImrWriteMask
|
||||
)
|
||||
{
|
||||
UINT16 DeviceId;
|
||||
UINT32 Data32;
|
||||
|
||||
//
|
||||
// Check what Soc we are running on (read Host bridge DeviceId)
|
||||
//
|
||||
DeviceId = QNCMmPci16(0, MC_BUS, MC_DEV, MC_FUN, PCI_DEVICE_ID_OFFSET);
|
||||
|
||||
//
|
||||
// Disable IMR protection
|
||||
//
|
||||
if (DeviceId == QUARK2_MC_DEVICE_ID) {
|
||||
//
|
||||
// Disable IMR protection
|
||||
//
|
||||
Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
|
||||
Data32 &= ~IMR_EN;
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, Data32);
|
||||
|
||||
//
|
||||
// Validate IMR protection is disabled
|
||||
//
|
||||
Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
|
||||
ASSERT((Data32 & IMR_EN) == 0);
|
||||
|
||||
//
|
||||
// Update the IMR (IMRXL must be last as it may enable IMR violation checking)
|
||||
//
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, ImrLow);
|
||||
|
||||
//
|
||||
// Validate IMR protection is enabled/disabled
|
||||
//
|
||||
Data32 = QNCPortRead (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL);
|
||||
ASSERT((Data32 & IMR_EN) == (ImrLow & IMR_EN));
|
||||
} else {
|
||||
//
|
||||
// Disable IMR protection (allow all access)
|
||||
//
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, (UINT32)IMRX_ALL_ACCESS);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, (UINT32)IMRX_ALL_ACCESS);
|
||||
|
||||
//
|
||||
// Update the IMR (IMRXRM/IMRXWM must be last as they restrict IMR access)
|
||||
//
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXL, (ImrLow & ~IMR_EN));
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXH, ImrHigh);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXRM, ImrReadMask);
|
||||
QNCPortWrite (QUARK_NC_MEMORY_MANAGER_SB_PORT_ID, ImrBaseOffset+QUARK_NC_MEMORY_MANAGER_IMRXWM, ImrWriteMask);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QncIClkAndThenOr (
|
||||
UINT32 RegAddress,
|
||||
UINT32 AndValue,
|
||||
UINT32 OrValue
|
||||
)
|
||||
{
|
||||
UINT32 RegValue;
|
||||
//
|
||||
// Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
|
||||
// should always consist of a READ from the address followed by 2 identical
|
||||
// WRITEs to that address.
|
||||
//
|
||||
RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
|
||||
RegValue &= AndValue;
|
||||
RegValue |= OrValue;
|
||||
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
||||
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
||||
}
|
||||
|
||||
VOID
|
||||
EFIAPI
|
||||
QncIClkOr (
|
||||
UINT32 RegAddress,
|
||||
UINT32 OrValue
|
||||
)
|
||||
{
|
||||
UINT32 RegValue;
|
||||
//
|
||||
// Whenever an iCLK SB register (Endpoint 32h) is being programmed the access
|
||||
// should always consist of a READ from the address followed by 2 identical
|
||||
// WRITEs to that address.
|
||||
//
|
||||
RegValue = QNCAltPortRead (QUARK_ICLK_SB_PORT_ID, RegAddress);
|
||||
RegValue |= OrValue;
|
||||
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
||||
QNCAltPortWrite (QUARK_ICLK_SB_PORT_ID, RegAddress, RegValue);
|
||||
}
|
@@ -0,0 +1,43 @@
|
||||
## @file
|
||||
# Base Intel QNC Library Instance
|
||||
#
|
||||
# Intel QNC internal network access Library Instance
|
||||
#
|
||||
# Copyright (c) 2013-2015 Intel Corporation.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = QNCAccessLib
|
||||
FILE_GUID = CC13B9FB-DAF5-4b42-907F-122216787C05
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = QNCAccessLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
QNCAccessLib.c
|
||||
BaseAccess.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DebugLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
|
@@ -0,0 +1,148 @@
|
||||
/** @file
|
||||
Runtime Lib function for QNC internal network access.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include <PiDxe.h>
|
||||
|
||||
#include <Guid/EventGroup.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiRuntimeLib.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
|
||||
///
|
||||
/// Set Virtual Address Map Event
|
||||
///
|
||||
EFI_EVENT mDxeRuntimeQncAccessLibVirtualNotifyEvent = NULL;
|
||||
|
||||
///
|
||||
/// Module global that contains the base physical address of the PCI Express MMIO range.
|
||||
///
|
||||
UINTN mDxeRuntimeQncAccessLibPciExpressBaseAddress = 0;
|
||||
|
||||
/**
|
||||
Convert the physical PCI Express MMIO address to a virtual address.
|
||||
|
||||
@param[in] Event The event that is being processed.
|
||||
@param[in] Context The Event Context.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
DxeRuntimeQncAccessLibVirtualNotify (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Convert the physical PCI Express MMIO address to a virtual address.
|
||||
//
|
||||
Status = EfiConvertPointer (0, (VOID **) &mDxeRuntimeQncAccessLibPciExpressBaseAddress);
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
The constructor function to setup globals and goto virtual mode notify.
|
||||
|
||||
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The constructor completed successfully.
|
||||
@retval Other value The constructor did not complete successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DxeRuntimeQncAccessLibConstructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Cache the physical address of the PCI Express MMIO range into a module global variable
|
||||
//
|
||||
mDxeRuntimeQncAccessLibPciExpressBaseAddress = (UINTN) PcdGet64(PcdPciExpressBaseAddress);
|
||||
|
||||
//
|
||||
// Register SetVirtualAddressMap () notify function
|
||||
//
|
||||
Status = gBS->CreateEventEx (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_NOTIFY,
|
||||
DxeRuntimeQncAccessLibVirtualNotify,
|
||||
NULL,
|
||||
&gEfiEventVirtualAddressChangeGuid,
|
||||
&mDxeRuntimeQncAccessLibVirtualNotifyEvent
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The destructor function frees any allocated buffers and closes the Set Virtual
|
||||
Address Map event.
|
||||
|
||||
@param ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The destructor completed successfully.
|
||||
@retval Other value The destructor did not complete successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DxeRuntimeQncAccessLibDestructor (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Close the Set Virtual Address Map event
|
||||
//
|
||||
Status = gBS->CloseEvent (mDxeRuntimeQncAccessLibVirtualNotifyEvent);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Gets the base address of PCI Express for Quark North Cluster.
|
||||
|
||||
@return The base address of PCI Express for Quark North Cluster.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
QncGetPciExpressBaseAddress (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// If system goes to virtual mode then virtual notify callback will update
|
||||
// mDxeRuntimeQncAccessLibPciExpressBaseAddress with virtual address of
|
||||
// PCIe memory base.
|
||||
//
|
||||
return mDxeRuntimeQncAccessLibPciExpressBaseAddress;
|
||||
}
|
||||
|
@@ -0,0 +1,49 @@
|
||||
## @file
|
||||
# DXE Runtime Intel QNC Library Instance
|
||||
#
|
||||
# Intel QNC internal network access Library Instance.
|
||||
#
|
||||
# Copyright (c) 2013-2015 Intel Corporation.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = RuntimeQNCAccessLib
|
||||
FILE_GUID = E6B51D93-E4C8-4425-9FA9-9DED814220F9
|
||||
MODULE_TYPE = DXE_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = QNCAccessLib|DXE_RUNTIME_DRIVER
|
||||
CONSTRUCTOR = DxeRuntimeQncAccessLibConstructor
|
||||
DESTRUCTOR = DxeRuntimeQncAccessLibDestructor
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32
|
||||
#
|
||||
|
||||
[Sources]
|
||||
QNCAccessLib.c
|
||||
RuntimeAccess.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DebugLib
|
||||
PcdLib
|
||||
UefiBootServicesTableLib
|
||||
UefiRuntimeLib
|
||||
|
||||
[Pcd]
|
||||
gEfiMdePkgTokenSpaceGuid.PcdPciExpressBaseAddress
|
322
QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
Normal file
322
QuarkSocPkg/QuarkNorthCluster/Library/QNCSmmLib/QNCSmmLib.c
Normal file
@@ -0,0 +1,322 @@
|
||||
/** @file
|
||||
QNC Smm Library Services that implements SMM Region access, S/W SMI generation and detection.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#include <Base.h>
|
||||
#include <IntelQNCRegs.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
|
||||
#define BOOT_SERVICE_SOFTWARE_SMI_DATA 0
|
||||
#define RUNTIME_SOFTWARE_SMI_DATA 1
|
||||
|
||||
/**
|
||||
Triggers a run time or boot time SMI.
|
||||
|
||||
This function triggers a software SMM interrupt and set the APMC status with an 8-bit Data.
|
||||
|
||||
@param Data The value to set the APMC status.
|
||||
|
||||
**/
|
||||
VOID
|
||||
InternalTriggerSmi (
|
||||
IN UINT8 Data
|
||||
)
|
||||
{
|
||||
UINT16 PM1BLK_Base;
|
||||
UINT16 GPE0BLK_Base;
|
||||
UINT32 NewValue;
|
||||
|
||||
//
|
||||
// Get PM1BLK_Base & GPE0BLK_Base
|
||||
//
|
||||
PM1BLK_Base = PcdGet16 (PcdPm1blkIoBaseAddress);
|
||||
GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
|
||||
|
||||
|
||||
//
|
||||
// Enable APM SMI
|
||||
//
|
||||
IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIE), B_QNC_GPE0BLK_SMIE_APM);
|
||||
|
||||
//
|
||||
// Enable SMI globally
|
||||
//
|
||||
NewValue = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
|
||||
NewValue |= SMI_EN;
|
||||
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, NewValue);
|
||||
|
||||
//
|
||||
// Set APM_STS
|
||||
//
|
||||
IoWrite8 (PcdGet16 (PcdSmmDataPort), Data);
|
||||
|
||||
//
|
||||
// Generate the APM SMI
|
||||
//
|
||||
IoWrite8 (PcdGet16 (PcdSmmActivationPort), PcdGet8 (PcdSmmActivationData));
|
||||
|
||||
//
|
||||
// Clear the APM SMI Status Bit
|
||||
//
|
||||
IoWrite32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_APM);
|
||||
|
||||
//
|
||||
// Set the EOS Bit
|
||||
//
|
||||
IoOr32 ((GPE0BLK_Base + R_QNC_GPE0BLK_SMIS), B_QNC_GPE0BLK_SMIS_EOS);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Triggers an SMI at boot time.
|
||||
|
||||
This function triggers a software SMM interrupt at boot time.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TriggerBootServiceSoftwareSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
InternalTriggerSmi (BOOT_SERVICE_SOFTWARE_SMI_DATA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Triggers an SMI at run time.
|
||||
|
||||
This function triggers a software SMM interrupt at run time.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
TriggerRuntimeSoftwareSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
InternalTriggerSmi (RUNTIME_SOFTWARE_SMI_DATA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Gets the software SMI data.
|
||||
|
||||
This function tests if a software SMM interrupt happens. If a software SMI happens,
|
||||
it retrieves the SMM data and returns it as a non-negative value; otherwise a negative
|
||||
value is returned.
|
||||
|
||||
@return Data The data retrieved from SMM data port in case of a software SMI;
|
||||
otherwise a negative value.
|
||||
|
||||
**/
|
||||
INTN
|
||||
InternalGetSwSmiData (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT8 SmiStatus;
|
||||
UINT8 Data;
|
||||
|
||||
SmiStatus = IoRead8 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_SMIS);
|
||||
if (((SmiStatus & B_QNC_GPE0BLK_SMIS_APM) != 0) &&
|
||||
(IoRead8 (PcdGet16 (PcdSmmActivationPort)) == PcdGet8 (PcdSmmActivationData))) {
|
||||
Data = IoRead8 (PcdGet16 (PcdSmmDataPort));
|
||||
return (INTN)(UINTN)Data;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test if a boot time software SMI happened.
|
||||
|
||||
This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
|
||||
it was triggered at boot time, it returns TRUE. Otherwise, it returns FALSE.
|
||||
|
||||
@retval TRUE A software SMI triggered at boot time happened.
|
||||
@retval FLASE No software SMI happened or the software SMI was triggered at run time.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsBootServiceSoftwareSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (BOOLEAN) (InternalGetSwSmiData () == BOOT_SERVICE_SOFTWARE_SMI_DATA);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Test if a run time software SMI happened.
|
||||
|
||||
This function tests if a software SMM interrupt happened. If a software SMM interrupt happened and
|
||||
it was triggered at run time, it returns TRUE. Otherwise, it returns FALSE.
|
||||
|
||||
@retval TRUE A software SMI triggered at run time happened.
|
||||
@retval FLASE No software SMI happened or the software SMI was triggered at boot time.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
IsRuntimeSoftwareSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (BOOLEAN) (InternalGetSwSmiData () == RUNTIME_SOFTWARE_SMI_DATA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
Clear APM SMI Status Bit; Set the EOS bit.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ClearSmi (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
|
||||
UINT16 GPE0BLK_Base;
|
||||
|
||||
//
|
||||
// Get GpeBase
|
||||
//
|
||||
GPE0BLK_Base = (UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF);
|
||||
|
||||
//
|
||||
// Clear the APM SMI Status Bit
|
||||
//
|
||||
IoOr16 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_APM);
|
||||
|
||||
//
|
||||
// Set the EOS Bit
|
||||
//
|
||||
IoOr32 (GPE0BLK_Base + R_QNC_GPE0BLK_SMIS, B_QNC_GPE0BLK_SMIS_EOS);
|
||||
}
|
||||
|
||||
/**
|
||||
This routine is the chipset code that accepts a request to "open" a region of SMRAM.
|
||||
The region could be legacy ABSEG, HSEG, or TSEG near top of physical memory.
|
||||
The use of "open" means that the memory is visible from all boot-service
|
||||
and SMM agents.
|
||||
|
||||
@retval FALSE Cannot open a locked SMRAM region
|
||||
@retval TRUE Success to open SMRAM region.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
QNCOpenSmramRegion (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Smram;
|
||||
|
||||
// Read the SMRAM register
|
||||
Smram = QncHsmmcRead ();
|
||||
|
||||
//
|
||||
// Is the platform locked?
|
||||
//
|
||||
if (Smram & SMM_LOCKED) {
|
||||
// Cannot Open a locked region
|
||||
DEBUG ((EFI_D_WARN, "Cannot open a locked SMRAM region\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Open all SMRAM regions for Host access only
|
||||
//
|
||||
Smram |= (SMM_WRITE_OPEN | SMM_READ_OPEN); // Open for Host.
|
||||
Smram &= ~(NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN); // Not for others.
|
||||
|
||||
//
|
||||
// Write the SMRAM register
|
||||
//
|
||||
QncHsmmcWrite (Smram);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
This routine is the chipset code that accepts a request to "close" a region of SMRAM.
|
||||
The region could be legacy AB or TSEG near top of physical memory.
|
||||
The use of "close" means that the memory is only visible from SMM agents,
|
||||
not from BS or RT code.
|
||||
|
||||
@retval FALSE Cannot open a locked SMRAM region
|
||||
@retval TRUE Success to open SMRAM region.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
QNCCloseSmramRegion (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Smram;
|
||||
|
||||
// Read the SMRAM register.
|
||||
Smram = QncHsmmcRead ();
|
||||
|
||||
//
|
||||
// Is the platform locked?
|
||||
//
|
||||
if(Smram & SMM_LOCKED) {
|
||||
// Cannot Open a locked region
|
||||
DEBUG ((EFI_D_WARN, "Cannot close a locked SMRAM region\n"));
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Smram &= (~(SMM_WRITE_OPEN | SMM_READ_OPEN | NON_HOST_SMM_WR_OPEN | NON_HOST_SMM_RD_OPEN));
|
||||
|
||||
QncHsmmcWrite (Smram);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
This routine is the chipset code that accepts a request to "lock" SMRAM.
|
||||
The region could be legacy AB or TSEG near top of physical memory.
|
||||
The use of "lock" means that the memory can no longer be opened
|
||||
to BS state.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
QNCLockSmramRegion (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT32 Smram;
|
||||
|
||||
// Read the SMRAM register.
|
||||
Smram = QncHsmmcRead ();
|
||||
if(Smram & SMM_LOCKED) {
|
||||
DEBUG ((EFI_D_WARN, "SMRAM region already locked!\n"));
|
||||
}
|
||||
Smram |= SMM_LOCKED;
|
||||
|
||||
QncHsmmcWrite (Smram);
|
||||
|
||||
return;
|
||||
}
|
@@ -0,0 +1,51 @@
|
||||
## @file
|
||||
# Component description file for Intel QNC SMM Library.
|
||||
#
|
||||
# QNC SMM Library that layers on top of the I/O Library to directly
|
||||
# access SMM power management registers.
|
||||
#
|
||||
# Copyright (c) 2013-2015 Intel Corporation.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = QNCSmmLib
|
||||
FILE_GUID = 8A9A62F5-758B-4965-A28B-0AAC292FBD89
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = SmmLib
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
QNCSmmLib.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PcdLib
|
||||
IoLib
|
||||
DebugLib
|
||||
QNCAccessLib
|
||||
|
||||
[Pcd]
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmDataPort
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationPort
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmmActivationData
|
@@ -0,0 +1,322 @@
|
||||
/** @file
|
||||
System reset Library Services. This library class provides a set of
|
||||
methods to reset whole system with manipulate QNC.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <Base.h>
|
||||
#include <IntelQNCBase.h>
|
||||
#include <QNCAccess.h>
|
||||
|
||||
#include <Uefi/UefiBaseType.h>
|
||||
|
||||
#include <Library/ResetSystemLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/CpuLib.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
|
||||
//
|
||||
// Amount of time (seconds) before RTC alarm fires
|
||||
// This must be < BCD_BASE
|
||||
//
|
||||
#define PLATFORM_WAKE_SECONDS_BUFFER 0x06
|
||||
|
||||
//
|
||||
// RTC 'seconds' above which we will not read to avoid potential rollover
|
||||
//
|
||||
#define PLATFORM_RTC_ROLLOVER_LIMIT 0x47
|
||||
|
||||
//
|
||||
// BCD is base 10
|
||||
//
|
||||
#define BCD_BASE 0x0A
|
||||
|
||||
#define PCAT_RTC_ADDRESS_REGISTER 0x70
|
||||
#define PCAT_RTC_DATA_REGISTER 0x71
|
||||
|
||||
//
|
||||
// Dallas DS12C887 Real Time Clock
|
||||
//
|
||||
#define RTC_ADDRESS_SECONDS 0 // R/W Range 0..59
|
||||
#define RTC_ADDRESS_SECONDS_ALARM 1 // R/W Range 0..59
|
||||
#define RTC_ADDRESS_MINUTES 2 // R/W Range 0..59
|
||||
#define RTC_ADDRESS_MINUTES_ALARM 3 // R/W Range 0..59
|
||||
#define RTC_ADDRESS_HOURS 4 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
|
||||
#define RTC_ADDRESS_HOURS_ALARM 5 // R/W Range 1..12 or 0..23 Bit 7 is AM/PM
|
||||
#define RTC_ADDRESS_DAY_OF_THE_WEEK 6 // R/W Range 1..7
|
||||
#define RTC_ADDRESS_DAY_OF_THE_MONTH 7 // R/W Range 1..31
|
||||
#define RTC_ADDRESS_MONTH 8 // R/W Range 1..12
|
||||
#define RTC_ADDRESS_YEAR 9 // R/W Range 0..99
|
||||
#define RTC_ADDRESS_REGISTER_A 10 // R/W[0..6] R0[7]
|
||||
#define RTC_ADDRESS_REGISTER_B 11 // R/W
|
||||
#define RTC_ADDRESS_REGISTER_C 12 // RO
|
||||
#define RTC_ADDRESS_REGISTER_D 13 // RO
|
||||
#define RTC_ADDRESS_CENTURY 50 // R/W Range 19..20 Bit 8 is R/W
|
||||
|
||||
/**
|
||||
Wait for an RTC update to happen
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
WaitForRTCUpdate (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT8 Data8;
|
||||
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
if ((Data8 & BIT7) == BIT7) {
|
||||
while ((Data8 & BIT7) == BIT7) {
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
}
|
||||
|
||||
} else {
|
||||
while ((Data8 & BIT7) == 0) {
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
}
|
||||
|
||||
while ((Data8 & BIT7) == BIT7) {
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_A);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Calling this function causes a system-wide reset. This sets
|
||||
all circuitry within the system to its initial state. This type of reset
|
||||
is asynchronous to system operation and operates without regard to
|
||||
cycle boundaries.
|
||||
|
||||
System reset should not return, if it returns, it means the system does
|
||||
not support cold reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetCold (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Reference to QuarkNcSocId BWG
|
||||
// Setting bit 1 will generate a warm reset, driving only RSTRDY# low
|
||||
//
|
||||
IoWrite8 (RST_CNT, B_RST_CNT_COLD_RST);
|
||||
}
|
||||
|
||||
/**
|
||||
Calling this function causes a system-wide initialization. The processors
|
||||
are set to their initial state, and pending cycles are not corrupted.
|
||||
|
||||
System reset should not return, if it returns, it means the system does
|
||||
not support warm reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetWarm (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Reference to QuarkNcSocId BWG
|
||||
// Setting bit 1 will generate a warm reset, driving only RSTRDY# low
|
||||
//
|
||||
IoWrite8 (RST_CNT, B_RST_CNT_WARM_RST);
|
||||
}
|
||||
|
||||
/**
|
||||
Calling this function causes the system to enter a power state equivalent
|
||||
to the ACPI G2/S5 or G3 states.
|
||||
|
||||
System shutdown should not return, if it returns, it means the system does
|
||||
not support shut down reset.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ResetShutdown (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Reference to QuarkNcSocId BWG
|
||||
// Disable RTC Alarm : (RTC Enable at PM1BLK + 02h[10]))
|
||||
//
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, 0);
|
||||
|
||||
//
|
||||
// Firstly, GPE0_EN should be disabled to
|
||||
// avoid any GPI waking up the system from S5
|
||||
//
|
||||
IoWrite32 ((UINT16)(LpcPciCfg32 (R_QNC_LPC_GPE0BLK) & 0xFFFF) + R_QNC_GPE0BLK_GPE0E, 0);
|
||||
|
||||
//
|
||||
// Reference to QuarkNcSocId BWG
|
||||
// Disable Resume Well GPIO : (GPIO bits in GPIOBASE + 34h[8:0])
|
||||
//
|
||||
IoWrite32 (PcdGet16 (PcdGbaIoBaseAddress) + R_QNC_GPIO_RGGPE_RESUME_WELL, 0);
|
||||
|
||||
//
|
||||
// No power button status bit to clear for our platform, go to next step.
|
||||
//
|
||||
|
||||
//
|
||||
// Finally, transform system into S5 sleep state
|
||||
//
|
||||
IoAndThenOr32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, 0xffffc3ff, B_QNC_PM1BLK_PM1C_SLPEN | V_S5);
|
||||
}
|
||||
|
||||
/**
|
||||
Calling this function causes the system to enter a power state for capsule
|
||||
update.
|
||||
|
||||
Reset update should not return, if it returns, it means the system does
|
||||
not support capsule update.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
EnterS3WithImmediateWake (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINT8 Data8;
|
||||
UINT16 Data16;
|
||||
UINT32 Data32;
|
||||
UINTN Eflags;
|
||||
UINTN RegCr0;
|
||||
EFI_TIME EfiTime;
|
||||
UINT32 SmiEnSave;
|
||||
|
||||
Eflags = AsmReadEflags ();
|
||||
if ( (Eflags & 0x200) ) {
|
||||
DisableInterrupts ();
|
||||
}
|
||||
|
||||
//
|
||||
// Write all cache data to memory because processor will lost power
|
||||
//
|
||||
AsmWbinvd();
|
||||
RegCr0 = AsmReadCr0();
|
||||
AsmWriteCr0 (RegCr0 | 0x060000000);
|
||||
|
||||
SmiEnSave = QNCPortRead (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC);
|
||||
QNCPortWrite (QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QNC_MSG_FSBIC_REG_HMISC, (SmiEnSave & ~SMI_EN));
|
||||
|
||||
//
|
||||
// Pogram RTC alarm for immediate WAKE
|
||||
//
|
||||
|
||||
//
|
||||
// Disable SMI sources
|
||||
//
|
||||
IoWrite16 (PcdGet16 (PcdGpe0blkIoBaseAddress) + R_QNC_GPE0BLK_SMIE, 0);
|
||||
|
||||
//
|
||||
// Disable RTC alarm interrupt
|
||||
//
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 & ~BIT5));
|
||||
|
||||
//
|
||||
// Clear RTC alarm if already set
|
||||
//
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_C);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER); // Read clears alarm status
|
||||
|
||||
//
|
||||
// Disable all WAKE events
|
||||
//
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, B_QNC_PM1BLK_PM1E_PWAKED);
|
||||
|
||||
//
|
||||
// Clear all WAKE status bits
|
||||
//
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1S, B_QNC_PM1BLK_PM1S_ALL);
|
||||
|
||||
//
|
||||
// Avoid RTC rollover
|
||||
//
|
||||
do {
|
||||
WaitForRTCUpdate();
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);
|
||||
EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
} while (EfiTime.Second > PLATFORM_RTC_ROLLOVER_LIMIT);
|
||||
|
||||
//
|
||||
// Read RTC time
|
||||
//
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS);
|
||||
EfiTime.Hour = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES);
|
||||
EfiTime.Minute = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS);
|
||||
EfiTime.Second = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
|
||||
//
|
||||
// Set RTC alarm
|
||||
//
|
||||
|
||||
//
|
||||
// Add PLATFORM_WAKE_SECONDS_BUFFER to current EfiTime.Second
|
||||
// The maths is to allow for the fact we are adding to a BCD number and require the answer to be BCD (EfiTime.Second)
|
||||
//
|
||||
if ((BCD_BASE - (EfiTime.Second & 0x0F)) <= PLATFORM_WAKE_SECONDS_BUFFER) {
|
||||
Data8 = (((EfiTime.Second & 0xF0) + 0x10) + (PLATFORM_WAKE_SECONDS_BUFFER - (BCD_BASE - (EfiTime.Second & 0x0F))));
|
||||
} else {
|
||||
Data8 = EfiTime.Second + PLATFORM_WAKE_SECONDS_BUFFER;
|
||||
}
|
||||
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_HOURS_ALARM);
|
||||
IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Hour);
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_MINUTES_ALARM);
|
||||
IoWrite8 (PCAT_RTC_DATA_REGISTER, EfiTime.Minute);
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_SECONDS_ALARM);
|
||||
IoWrite8 (PCAT_RTC_DATA_REGISTER, Data8);
|
||||
|
||||
//
|
||||
// Enable RTC alarm interrupt
|
||||
//
|
||||
IoWrite8 (PCAT_RTC_ADDRESS_REGISTER, RTC_ADDRESS_REGISTER_B);
|
||||
Data8 = IoRead8 (PCAT_RTC_DATA_REGISTER);
|
||||
IoWrite8 (PCAT_RTC_DATA_REGISTER, (Data8 | BIT5));
|
||||
|
||||
//
|
||||
// Enable RTC alarm as WAKE event
|
||||
//
|
||||
Data16 = IoRead16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E);
|
||||
IoWrite16 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1E, (Data16 | B_QNC_PM1BLK_PM1E_RTC));
|
||||
|
||||
//
|
||||
// Enter S3
|
||||
//
|
||||
Data32 = IoRead32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C);
|
||||
Data32 = (UINT32) ((Data32 & 0xffffc3fe) | V_S3 | B_QNC_PM1BLK_PM1C_SCIEN);
|
||||
IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);
|
||||
Data32 = Data32 | B_QNC_PM1BLK_PM1C_SLPEN;
|
||||
IoWrite32 (PcdGet16 (PcdPm1blkIoBaseAddress) + R_QNC_PM1BLK_PM1C, Data32);
|
||||
|
||||
//
|
||||
// Enable Interrupt if it's enabled before
|
||||
//
|
||||
if ( (Eflags & 0x200) ) {
|
||||
EnableInterrupts ();
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,52 @@
|
||||
## @file
|
||||
# Component description file for Intel QuarkNcSocId Reset System Library.
|
||||
#
|
||||
# Reset System Library implementation that bases on QNC.
|
||||
#
|
||||
# Copyright (c) 2013-2015 Intel Corporation.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = ResetSystemLib
|
||||
FILE_GUID = AD33A56E-3AAD-40ac-91B1-FA861E8D9D85
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = ResetSystemLib
|
||||
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64
|
||||
#
|
||||
|
||||
[Sources]
|
||||
ResetSystemLib.c
|
||||
|
||||
|
||||
[Packages]
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PcdLib
|
||||
IoLib
|
||||
BaseLib
|
||||
CpuLib
|
||||
QNCAccessLib
|
||||
|
||||
[Pcd]
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdGbaIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdPm1blkIoBaseAddress
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdGpe0blkIoBaseAddress
|
@@ -0,0 +1,31 @@
|
||||
/** @file
|
||||
Common header file shared by all source files.
|
||||
|
||||
This file includes package header files, library classes and protocol, PPI & GUID definitions.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
**/
|
||||
|
||||
#ifndef __COMMON_HEADER_H_
|
||||
#define __COMMON_HEADER_H_
|
||||
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <Base.h>
|
||||
|
||||
#include <Library/SmbusLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/PciLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/PcdLib.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
|
||||
#endif
|
803
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c
Normal file
803
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.c
Normal file
@@ -0,0 +1,803 @@
|
||||
/** @file
|
||||
Intel QNC SMBUS library implementation built upon I/O library.
|
||||
|
||||
Copyright (c) 2013-2015 Intel Corporation.
|
||||
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
//
|
||||
// Include common header file for this module.
|
||||
//
|
||||
#include "CommonHeader.h"
|
||||
|
||||
/**
|
||||
Gets Io port base address of Smbus Host Controller.
|
||||
|
||||
This internal function depends on a feature flag named PcdIchSmbusFixedIoPortBaseAddress
|
||||
to retrieve Smbus Io port base. If that feature flag is true, it will get Smbus Io port base
|
||||
address from a preset Pcd entry named PcdIchSmbusIoPortBaseAddress; otherwise, it will always
|
||||
read Pci configuration space to get that value in each Smbus bus transaction.
|
||||
|
||||
@return The Io port base address of Smbus host controller.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
InternalGetSmbusIoPortBaseAddress (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN IoPortBaseAddress;
|
||||
|
||||
if (FeaturePcdGet (PcdSmbaIoBaseAddressFixed)) {
|
||||
IoPortBaseAddress = (UINTN) PcdGet16 (PcdSmbaIoBaseAddress);
|
||||
} else {
|
||||
IoPortBaseAddress = (UINTN) LpcPciCfg32 (R_QNC_LPC_SMBUS_BASE) & B_QNC_LPC_SMBUS_BASE_MASK;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure that the IO port base address has been properly set.
|
||||
//
|
||||
ASSERT (IoPortBaseAddress != 0);
|
||||
|
||||
return IoPortBaseAddress;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Acquires the ownership of SMBUS.
|
||||
|
||||
This internal function reads the host state register.
|
||||
If the SMBUS is not available, RETURN_TIMEOUT is returned;
|
||||
Otherwise, it performs some basic initializations and returns
|
||||
RETURN_SUCCESS.
|
||||
|
||||
@param IoPortBaseAddress The Io port base address of Smbus Host controller.
|
||||
|
||||
@retval RETURN_SUCCESS The SMBUS command was executed successfully.
|
||||
@retval RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
InternalSmBusAcquire (
|
||||
UINTN IoPortBaseAddress
|
||||
)
|
||||
{
|
||||
|
||||
//
|
||||
// Clear host status register and exit.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, 0);
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, 0);
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, 0);
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
|
||||
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Starts the SMBUS transaction and waits until the end.
|
||||
|
||||
This internal function start the SMBUS transaction and waits until the transaction
|
||||
of SMBUS is over by polling the INTR bit of Host status register.
|
||||
If the SMBUS is not available, RETURN_TIMEOUT is returned;
|
||||
Otherwise, it performs some basic initializations and returns
|
||||
RETURN_SUCCESS.
|
||||
|
||||
@param IoPortBaseAddress The Io port base address of Smbus Host controller.
|
||||
@param HostControl The Host control command to start SMBUS transaction.
|
||||
|
||||
@retval RETURN_SUCCESS The SMBUS command was executed successfully.
|
||||
@retval RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect).
|
||||
@retval RETURN_DEVICE_ERROR The request was not completed because a failure reflected
|
||||
in the Host Status Register bit. Device errors are
|
||||
a result of a transaction collision, illegal command field,
|
||||
unclaimed cycle (host initiated), or bus errors (collisions).
|
||||
|
||||
**/
|
||||
RETURN_STATUS
|
||||
InternalSmBusStart (
|
||||
IN UINTN IoPortBaseAddress,
|
||||
IN UINT8 HostControl
|
||||
)
|
||||
{
|
||||
UINT8 HostStatus;
|
||||
|
||||
//
|
||||
// Set Host Control Register (Initiate Operation, Interrupt disabled).
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL, HostControl + B_QNC_SMBUS_START);
|
||||
|
||||
do {
|
||||
//
|
||||
// Poll INTR bit of Host Status Register.
|
||||
//
|
||||
HostStatus = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS);
|
||||
} while ((HostStatus & (B_QNC_SMBUS_BYTE_DONE_STS | B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0);
|
||||
|
||||
if ((HostStatus & (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR)) == 0) {
|
||||
return RETURN_SUCCESS;
|
||||
}
|
||||
//
|
||||
// Clear error bits of Host Status Register.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, (B_QNC_SMBUS_DERR | B_QNC_SMBUS_BERR));
|
||||
|
||||
return RETURN_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS quick, byte or word command.
|
||||
|
||||
This internal function executes an SMBUS quick, byte or word commond.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
|
||||
@param HostControl The value of Host Control Register to set.
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Value The byte/word write to the SMBUS.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The byte/word read from the SMBUS.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
InternalSmBusNonBlock (
|
||||
IN UINT8 HostControl,
|
||||
IN UINTN SmBusAddress,
|
||||
IN UINT16 Value,
|
||||
OUT RETURN_STATUS *Status
|
||||
)
|
||||
{
|
||||
RETURN_STATUS ReturnStatus;
|
||||
UINTN IoPortBaseAddress;
|
||||
|
||||
IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
|
||||
|
||||
//
|
||||
// Try to acquire the ownership of QNC SMBUS.
|
||||
//
|
||||
ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
|
||||
if (RETURN_ERROR (ReturnStatus)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Host Commond Register.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
|
||||
//
|
||||
// Write value to Host Data 0 and Host Data 1 Registers.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) Value);
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD1, (UINT8) (Value >> 8));
|
||||
|
||||
|
||||
//
|
||||
// Set SMBUS slave address for the device to send/receive from.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);
|
||||
//
|
||||
// Start the SMBUS transaction and wait for the end.
|
||||
//
|
||||
ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
|
||||
//
|
||||
// Read value from Host Data 0 and Host Data 1 Registers.
|
||||
//
|
||||
Value = (UINT16)(IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD1) << 8);
|
||||
Value = (UINT16)(Value | IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0));
|
||||
|
||||
//
|
||||
// Clear Host Status Register and Auxiliary Status Register.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
|
||||
|
||||
Done:
|
||||
if (Status != NULL) {
|
||||
*Status = ReturnStatus;
|
||||
}
|
||||
|
||||
return Value;
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS quick read command.
|
||||
|
||||
Executes an SMBUS quick read command on the SMBUS device specified by SmBusAddress.
|
||||
Only the SMBUS slave address field of SmBusAddress is required.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If PEC is set in SmBusAddress, then ASSERT().
|
||||
If Command in SmBusAddress is not zero, then ASSERT().
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmBusQuickRead (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
|
||||
ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_QUICK,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
|
||||
0,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS quick write command.
|
||||
|
||||
Executes an SMBUS quick write command on the SMBUS device specified by SmBusAddress.
|
||||
Only the SMBUS slave address field of SmBusAddress is required.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If PEC is set in SmBusAddress, then ASSERT().
|
||||
If Command in SmBusAddress is not zero, then ASSERT().
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmBusQuickWrite (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (!SMBUS_LIB_PEC (SmBusAddress));
|
||||
ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_QUICK,
|
||||
SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
|
||||
0,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS receive byte command.
|
||||
|
||||
Executes an SMBUS receive byte command on the SMBUS device specified by SmBusAddress.
|
||||
Only the SMBUS slave address field of SmBusAddress is required.
|
||||
The byte received from the SMBUS is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Command in SmBusAddress is not zero, then ASSERT().
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The byte received from the SMBUS.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
SmBusReceiveByte (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return (UINT8) InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_BYTE,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
|
||||
0,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS send byte command.
|
||||
|
||||
Executes an SMBUS send byte command on the SMBUS device specified by SmBusAddress.
|
||||
The byte specified by Value is sent.
|
||||
Only the SMBUS slave address field of SmBusAddress is required. Value is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Command in SmBusAddress is not zero, then ASSERT().
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Value The 8-bit value to send.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The parameter of Value.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
SmBusSendByte (
|
||||
IN UINTN SmBusAddress,
|
||||
IN UINT8 Value,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_COMMAND (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return (UINT8) InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_BYTE,
|
||||
SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
|
||||
Value,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS read data byte command.
|
||||
|
||||
Executes an SMBUS read data byte command on the SMBUS device specified by SmBusAddress.
|
||||
Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
|
||||
The 8-bit value read from the SMBUS is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The byte read from the SMBUS.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
SmBusReadDataByte (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return (UINT8) InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
|
||||
0,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS write data byte command.
|
||||
|
||||
Executes an SMBUS write data byte command on the SMBUS device specified by SmBusAddress.
|
||||
The 8-bit value specified by Value is written.
|
||||
Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
|
||||
Value is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Value The 8-bit value to write.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The parameter of Value.
|
||||
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
SmBusWriteDataByte (
|
||||
IN UINTN SmBusAddress,
|
||||
IN UINT8 Value,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return (UINT8) InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_BYTE_DATA,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
|
||||
Value,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS read data word command.
|
||||
|
||||
Executes an SMBUS read data word command on the SMBUS device specified by SmBusAddress.
|
||||
Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
|
||||
The 16-bit value read from the SMBUS is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The byte read from the SMBUS.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
EFIAPI
|
||||
SmBusReadDataWord (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 2);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_WORD_DATA,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
|
||||
0,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS write data word command.
|
||||
|
||||
Executes an SMBUS write data word command on the SMBUS device specified by SmBusAddress.
|
||||
The 16-bit value specified by Value is written.
|
||||
Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
|
||||
Value is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Value The 16-bit value to write.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The parameter of Value.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
EFIAPI
|
||||
SmBusWriteDataWord (
|
||||
IN UINTN SmBusAddress,
|
||||
IN UINT16 Value,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 2);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_WORD_DATA,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
|
||||
Value,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS process call command.
|
||||
|
||||
Executes an SMBUS process call command on the SMBUS device specified by SmBusAddress.
|
||||
The 16-bit value specified by Value is written.
|
||||
Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
|
||||
The 16-bit value returned by the process call command is returned.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Value The 16-bit value to write.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The 16-bit value returned by the process call command.
|
||||
|
||||
**/
|
||||
UINT16
|
||||
EFIAPI
|
||||
SmBusProcessCall (
|
||||
IN UINTN SmBusAddress,
|
||||
IN UINT16 Value,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) == 0);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return InternalSmBusNonBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_PROCESS_CALL,
|
||||
SmBusAddress & V_QNC_SMBUS_RW_SEL_WRITE,
|
||||
Value,
|
||||
Status
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS block command.
|
||||
|
||||
Executes an SMBUS block read, block write and block write-block read command
|
||||
on the SMBUS device specified by SmBusAddress.
|
||||
Bytes are read from the SMBUS and stored in Buffer.
|
||||
The number of bytes read is returned, and will never return a value larger than 32-bytes.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
|
||||
SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
|
||||
|
||||
@param HostControl The value of Host Control Register to set.
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
|
||||
@param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The number of bytes read from the SMBUS.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
InternalSmBusBlock (
|
||||
IN UINT8 HostControl,
|
||||
IN UINTN SmBusAddress,
|
||||
IN UINT8 *WriteBuffer,
|
||||
OUT UINT8 *ReadBuffer,
|
||||
OUT RETURN_STATUS *Status
|
||||
)
|
||||
{
|
||||
RETURN_STATUS ReturnStatus;
|
||||
UINTN Index;
|
||||
UINTN BytesCount;
|
||||
UINTN IoPortBaseAddress;
|
||||
|
||||
IoPortBaseAddress = InternalGetSmbusIoPortBaseAddress ();
|
||||
|
||||
BytesCount = SMBUS_LIB_LENGTH (SmBusAddress);
|
||||
|
||||
//
|
||||
// Try to acquire the ownership of ICH SMBUS.
|
||||
//
|
||||
ReturnStatus = InternalSmBusAcquire (IoPortBaseAddress);
|
||||
if (RETURN_ERROR (ReturnStatus)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Host Command Register.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HCMD, (UINT8) SMBUS_LIB_COMMAND (SmBusAddress));
|
||||
|
||||
//
|
||||
// Clear byte pointer of 32-byte buffer.
|
||||
//
|
||||
IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HCTL);
|
||||
|
||||
if (WriteBuffer != NULL) {
|
||||
//
|
||||
// Write the number of block to Host Block Data Byte Register.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HD0, (UINT8) BytesCount);
|
||||
//
|
||||
// Write data block to Host Block Data Register.
|
||||
//
|
||||
for (Index = 0; Index < BytesCount; Index++) {
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index, WriteBuffer[Index]);
|
||||
}
|
||||
}
|
||||
//
|
||||
// Set SMBUS slave address for the device to send/receive from.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_TSA, (UINT8) SmBusAddress);
|
||||
//
|
||||
// Start the SMBUS transaction and wait for the end.
|
||||
//
|
||||
ReturnStatus = InternalSmBusStart (IoPortBaseAddress, HostControl);
|
||||
if (RETURN_ERROR (ReturnStatus)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (ReadBuffer != NULL) {
|
||||
//
|
||||
// Read the number of block from host block data byte register.
|
||||
//
|
||||
BytesCount = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HD0);
|
||||
//
|
||||
// Write data block from Host Block Data Register.
|
||||
//
|
||||
for (Index = 0; Index < BytesCount; Index++) {
|
||||
ReadBuffer[Index] = IoRead8 (IoPortBaseAddress + R_QNC_SMBUS_HBD + (UINT8)Index);
|
||||
}
|
||||
}
|
||||
|
||||
Done:
|
||||
//
|
||||
// Clear Host Status Register and Auxiliary Status Register.
|
||||
//
|
||||
IoWrite8 (IoPortBaseAddress + R_QNC_SMBUS_HSTS, B_QNC_SMBUS_HSTS_ALL);
|
||||
|
||||
if (Status != NULL) {
|
||||
*Status = ReturnStatus;
|
||||
}
|
||||
|
||||
return BytesCount;
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS read block command.
|
||||
|
||||
Executes an SMBUS read block command on the SMBUS device specified by SmBusAddress.
|
||||
Only the SMBUS slave address and SMBUS command fields of SmBusAddress are required.
|
||||
Bytes are read from the SMBUS and stored in Buffer.
|
||||
The number of bytes read is returned, and will never return a value larger than 32-bytes.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
It is the caller's responsibility to make sure Buffer is large enough for the total number of bytes read.
|
||||
SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
|
||||
If Length in SmBusAddress is not zero, then ASSERT().
|
||||
If Buffer is NULL, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Buffer Pointer to the buffer to store the bytes read from the SMBUS.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The number of bytes read.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmBusReadBlock (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT VOID *Buffer,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (Buffer != NULL);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return InternalSmBusBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_BLOCK,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_READ,
|
||||
NULL,
|
||||
Buffer,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS write block command.
|
||||
|
||||
Executes an SMBUS write block command on the SMBUS device specified by SmBusAddress.
|
||||
The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
|
||||
Bytes are written to the SMBUS from Buffer.
|
||||
The number of bytes written is returned, and will never return a value larger than 32-bytes.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
If Length in SmBusAddress is zero or greater than 32, then ASSERT().
|
||||
If Buffer is NULL, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param Buffer Pointer to the buffer to store the bytes read from the SMBUS.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
|
||||
@return The number of bytes written.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmBusWriteBlock (
|
||||
IN UINTN SmBusAddress,
|
||||
OUT VOID *Buffer,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (Buffer != NULL);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
|
||||
return InternalSmBusBlock (
|
||||
V_QNC_SMBUS_HCTL_CMD_BLOCK,
|
||||
SmBusAddress | V_QNC_SMBUS_RW_SEL_WRITE,
|
||||
Buffer,
|
||||
NULL,
|
||||
Status
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Executes an SMBUS block process call command.
|
||||
|
||||
Executes an SMBUS block process call command on the SMBUS device specified by SmBusAddress.
|
||||
The SMBUS slave address, SMBUS command, and SMBUS length fields of SmBusAddress are required.
|
||||
Bytes are written to the SMBUS from WriteBuffer. Bytes are then read from the SMBUS into ReadBuffer.
|
||||
If Status is not NULL, then the status of the executed command is returned in Status.
|
||||
It is the caller's responsibility to make sure ReadBuffer is large enough for the total number of bytes read.
|
||||
SMBUS supports a maximum transfer size of 32 bytes, so Buffer does not need to be any larger than 32 bytes.
|
||||
If Length in SmBusAddress is zero or greater than 32, then ASSERT().
|
||||
If WriteBuffer is NULL, then ASSERT().
|
||||
If ReadBuffer is NULL, then ASSERT().
|
||||
If any reserved bits of SmBusAddress are set, then ASSERT().
|
||||
|
||||
@param SmBusAddress Address that encodes the SMBUS Slave Address,
|
||||
SMBUS Command, SMBUS Data Length, and PEC.
|
||||
@param WriteBuffer Pointer to the buffer of bytes to write to the SMBUS.
|
||||
@param ReadBuffer Pointer to the buffer of bytes to read from the SMBUS.
|
||||
@param Status Return status for the executed command.
|
||||
This is an optional parameter and may be NULL.
|
||||
RETURN_TIMEOUT A timeout occurred while executing the SMBUS command.
|
||||
RETURN_DEVICE_ERROR The request was not completed because a failure
|
||||
reflected in the Host Status Register bit. Device errors are a result
|
||||
of a transaction collision, illegal command field, unclaimed cycle
|
||||
(host initiated), or bus errors (collisions).
|
||||
RETURN_CRC_ERROR The checksum is not correct (PEC is incorrect)
|
||||
RETURN_UNSUPPORTED The SMBus operation is not supported.
|
||||
|
||||
@return The number of bytes written.
|
||||
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmBusBlockProcessCall (
|
||||
IN UINTN SmBusAddress,
|
||||
IN VOID *WriteBuffer,
|
||||
OUT VOID *ReadBuffer,
|
||||
OUT RETURN_STATUS *Status OPTIONAL
|
||||
)
|
||||
{
|
||||
ASSERT (WriteBuffer != NULL);
|
||||
ASSERT (ReadBuffer != NULL);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) >= 1);
|
||||
ASSERT (SMBUS_LIB_LENGTH (SmBusAddress) <= 32);
|
||||
ASSERT (SMBUS_LIB_RESERVED (SmBusAddress) == 0);
|
||||
if (Status != NULL) {
|
||||
*Status = RETURN_UNSUPPORTED;
|
||||
}
|
||||
return 0;
|
||||
}
|
53
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
Normal file
53
QuarkSocPkg/QuarkNorthCluster/Library/SmbusLib/SmbusLib.inf
Normal file
@@ -0,0 +1,53 @@
|
||||
## @file
|
||||
# Component description file for Intel QNC Smbus Library.
|
||||
#
|
||||
# SMBUS Library that layers on top of the I/O Library to directly
|
||||
# access a standard SMBUS host controller.
|
||||
#
|
||||
# Copyright (c) 2013-2015 Intel Corporation.
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SmbusLib
|
||||
FILE_GUID = 6F2F36B3-936B-4eb2-83C7-2987B4F9D4EB
|
||||
MODULE_TYPE = BASE
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = SmbusLib
|
||||
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
SmbusLib.c
|
||||
CommonHeader.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PcdLib
|
||||
DebugLib
|
||||
PciLib
|
||||
IoLib
|
||||
QNCAccessLib
|
||||
|
||||
[FeaturePcd]
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddressFixed
|
||||
|
||||
[Pcd]
|
||||
gEfiQuarkNcSocIdTokenSpaceGuid.PcdSmbaIoBaseAddress
|
@@ -0,0 +1,438 @@
|
||||
/** @file
|
||||
The Quark CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
|
||||
Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include <PiSmm.h>
|
||||
#include <Library/SmmCpuFeaturesLib.h>
|
||||
#include <Register/SmramSaveStateMap.h>
|
||||
#include <Library/QNCAccessLib.h>
|
||||
|
||||
#define EFI_MSR_SMRR_PHYS_MASK_VALID BIT11
|
||||
#define EFI_MSR_SMRR_MASK 0xFFFFF000
|
||||
|
||||
/**
|
||||
Called during the very first SMI into System Management Mode to initialize
|
||||
CPU features, including SMBASE, for the currently executing CPU. Since this
|
||||
is the first SMI, the SMRAM Save State Map is at the default address of
|
||||
SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET. The currently executing
|
||||
CPU is specified by CpuIndex and CpuIndex can be used to access information
|
||||
about the currently executing CPU in the ProcessorInfo array and the
|
||||
HotPlugCpuData data structure.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to initialize. The value
|
||||
must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] IsMonarch TRUE if the CpuIndex is the index of the CPU that
|
||||
was elected as monarch during System Management
|
||||
Mode initialization.
|
||||
FALSE if the CpuIndex is not the index of the CPU
|
||||
that was elected as monarch during System
|
||||
Management Mode initialization.
|
||||
@param[in] ProcessorInfo Pointer to an array of EFI_PROCESSOR_INFORMATION
|
||||
structures. ProcessorInfo[CpuIndex] contains the
|
||||
information for the currently executing CPU.
|
||||
@param[in] CpuHotPlugData Pointer to the CPU_HOT_PLUG_DATA structure that
|
||||
contains the ApidId and SmBase arrays.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesInitializeProcessor (
|
||||
IN UINTN CpuIndex,
|
||||
IN BOOLEAN IsMonarch,
|
||||
IN EFI_PROCESSOR_INFORMATION *ProcessorInfo,
|
||||
IN CPU_HOT_PLUG_DATA *CpuHotPlugData
|
||||
)
|
||||
{
|
||||
SMRAM_SAVE_STATE_MAP *CpuState;
|
||||
|
||||
//
|
||||
// Configure SMBASE.
|
||||
//
|
||||
CpuState = (SMRAM_SAVE_STATE_MAP *)(UINTN)(SMM_DEFAULT_SMBASE + SMRAM_SAVE_STATE_MAP_OFFSET);
|
||||
CpuState->x86.SMBASE = CpuHotPlugData->SmBase[CpuIndex];
|
||||
|
||||
//
|
||||
// Use QNC to initialize SMRR on Quark
|
||||
//
|
||||
QNCPortWrite(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSBASE, CpuHotPlugData->SmrrBase);
|
||||
QNCPortWrite(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK, (~(CpuHotPlugData->SmrrSize - 1) & EFI_MSR_SMRR_MASK) | EFI_MSR_SMRR_PHYS_MASK_VALID);
|
||||
}
|
||||
|
||||
/**
|
||||
This function updates the SMRAM save state on the currently executing CPU
|
||||
to resume execution at a specific address after an RSM instruction. This
|
||||
function must evaluate the SMRAM save state to determine the execution mode
|
||||
the RSM instruction resumes and update the resume execution address with
|
||||
either NewInstructionPointer32 or NewInstructionPoint. The auto HALT restart
|
||||
flag in the SMRAM save state must always be cleared. This function returns
|
||||
the value of the instruction pointer from the SMRAM save state that was
|
||||
replaced. If this function returns 0, then the SMRAM save state was not
|
||||
modified.
|
||||
|
||||
This function is called during the very first SMI on each CPU after
|
||||
SmmCpuFeaturesInitializeProcessor() to set a flag in normal execution mode
|
||||
to signal that the SMBASE of each CPU has been updated before the default
|
||||
SMBASE address is used for the first SMI to the next CPU.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to hook. The value
|
||||
must be between 0 and the NumberOfCpus
|
||||
field in the System Management System Table
|
||||
(SMST).
|
||||
@param[in] CpuState Pointer to SMRAM Save State Map for the
|
||||
currently executing CPU.
|
||||
@param[in] NewInstructionPointer32 Instruction pointer to use if resuming to
|
||||
32-bit execution mode from 64-bit SMM.
|
||||
@param[in] NewInstructionPointer Instruction pointer to use if resuming to
|
||||
same execution mode as SMM.
|
||||
|
||||
@retval 0 This function did modify the SMRAM save state.
|
||||
@retval > 0 The original instruction pointer value from the SMRAM save state
|
||||
before it was replaced.
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
SmmCpuFeaturesHookReturnFromSmm (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMRAM_SAVE_STATE_MAP *CpuState,
|
||||
IN UINT64 NewInstructionPointer32,
|
||||
IN UINT64 NewInstructionPointer
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Hook point in normal execution mode that allows the one CPU that was elected
|
||||
as monarch during System Management Mode initialization to perform additional
|
||||
initialization actions immediately after all of the CPUs have processed their
|
||||
first SMI and called SmmCpuFeaturesInitializeProcessor() relocating SMBASE
|
||||
into a buffer in SMRAM and called SmmCpuFeaturesHookReturnFromSmm().
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesSmmRelocationComplete (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Return the size, in bytes, of a custom SMI Handler in bytes. If 0 is
|
||||
returned, then a custom SMI handler is not provided by this library,
|
||||
and the default SMI handler must be used.
|
||||
|
||||
@retval 0 Use the default SMI handler.
|
||||
@retval > 0 Use the SMI handler installed by SmmCpuFeaturesInstallSmiHandler()
|
||||
The caller is required to allocate enough SMRAM for each CPU to
|
||||
support the size of the custom SMI handler.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmiHandlerSize (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Install a custom SMI handler for the CPU specified by CpuIndex. This function
|
||||
is only called if SmmCpuFeaturesGetSmiHandlerSize() returns a size is greater
|
||||
than zero and is called by the CPU that was elected as monarch during System
|
||||
Management Mode initialization.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to install the custom SMI handler.
|
||||
The value must be between 0 and the NumberOfCpus field
|
||||
in the System Management System Table (SMST).
|
||||
@param[in] SmBase The SMBASE address for the CPU specified by CpuIndex.
|
||||
@param[in] SmiStack The stack to use when an SMI is processed by the
|
||||
the CPU specified by CpuIndex.
|
||||
@param[in] StackSize The size, in bytes, if the stack used when an SMI is
|
||||
processed by the CPU specified by CpuIndex.
|
||||
@param[in] GdtBase The base address of the GDT to use when an SMI is
|
||||
processed by the CPU specified by CpuIndex.
|
||||
@param[in] GdtSize The size, in bytes, of the GDT used when an SMI is
|
||||
processed by the CPU specified by CpuIndex.
|
||||
@param[in] IdtBase The base address of the IDT to use when an SMI is
|
||||
processed by the CPU specified by CpuIndex.
|
||||
@param[in] IdtSize The size, in bytes, of the IDT used when an SMI is
|
||||
processed by the CPU specified by CpuIndex.
|
||||
@param[in] Cr3 The base address of the page tables to use when an SMI
|
||||
is processed by the CPU specified by CpuIndex.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesInstallSmiHandler (
|
||||
IN UINTN CpuIndex,
|
||||
IN UINT32 SmBase,
|
||||
IN VOID *SmiStack,
|
||||
IN UINTN StackSize,
|
||||
IN UINTN GdtBase,
|
||||
IN UINTN GdtSize,
|
||||
IN UINTN IdtBase,
|
||||
IN UINTN IdtSize,
|
||||
IN UINT32 Cr3
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Determines if MTRR registers must be configured to set SMRAM cache-ability
|
||||
when executing in System Management Mode.
|
||||
|
||||
@retval TRUE MTRR registers must be configured to set SMRAM cache-ability.
|
||||
@retval FALSE MTRR registers do not need to be configured to set SMRAM
|
||||
cache-ability.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesNeedConfigureMtrrs (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Disable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
|
||||
returns TRUE.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesDisableSmrr (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Use QNC to disable SMRR on Quark
|
||||
//
|
||||
QNCPortWrite(
|
||||
QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
|
||||
QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK,
|
||||
QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK) & ~EFI_MSR_SMRR_PHYS_MASK_VALID
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Enable SMRR register if SMRR is supported and SmmCpuFeaturesNeedConfigureMtrrs()
|
||||
returns TRUE.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesReenableSmrr (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Use QNC to enable SMRR on Quark
|
||||
//
|
||||
QNCPortWrite(
|
||||
QUARK_NC_HOST_BRIDGE_SB_PORT_ID,
|
||||
QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK,
|
||||
QNCPortRead(QUARK_NC_HOST_BRIDGE_SB_PORT_ID, QUARK_NC_HOST_BRIDGE_IA32_MTRR_SMRR_PHYSMASK) | EFI_MSR_SMRR_PHYS_MASK_VALID
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Processor specific hook point each time a CPU enters System Management Mode.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU that has entered SMM. The value
|
||||
must be between 0 and the NumberOfCpus field in the
|
||||
System Management System Table (SMST).
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesRendezvousEntry (
|
||||
IN UINTN CpuIndex
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Processor specific hook point each time a CPU exits System Management Mode.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU that is exiting SMM. The value must
|
||||
be between 0 and the NumberOfCpus field in the System
|
||||
Management System Table (SMST).
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesRendezvousExit (
|
||||
IN UINTN CpuIndex
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Check to see if an SMM register is supported by a specified CPU.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to check for SMM register support.
|
||||
The value must be between 0 and the NumberOfCpus field
|
||||
in the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to check for support.
|
||||
|
||||
@retval TRUE The SMM register specified by RegName is supported by the CPU
|
||||
specified by CpuIndex.
|
||||
@retval FALSE The SMM register specified by RegName is not supported by the
|
||||
CPU specified by CpuIndex.
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
SmmCpuFeaturesIsSmmRegisterSupported (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName
|
||||
)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current value of the SMM register for the specified CPU.
|
||||
If the SMM register is not supported, then 0 is returned.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to read the SMM register. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to read.
|
||||
|
||||
@return The value of the SMM register specified by RegName from the CPU
|
||||
specified by CpuIndex.
|
||||
**/
|
||||
UINT64
|
||||
EFIAPI
|
||||
SmmCpuFeaturesGetSmmRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the value of an SMM register on a specified CPU.
|
||||
If the SMM register is not supported, then no action is performed.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to write the SMM register. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] RegName Identifies the SMM register to write.
|
||||
registers are read-only.
|
||||
@param[in] Value The value to write to the SMM register.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesSetSmmRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN SMM_REG_NAME RegName,
|
||||
IN UINT64 Value
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
Read an SMM Save State register on the target processor. If this function
|
||||
returns EFI_UNSUPPORTED, then the caller is responsible for reading the
|
||||
SMM Save Sate register.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to read the SMM Save State. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] Register The SMM Save State register to read.
|
||||
@param[in] Width The number of bytes to read from the CPU save state.
|
||||
@param[out] Buffer Upon return, this holds the CPU register value read
|
||||
from the save state.
|
||||
|
||||
@retval EFI_SUCCESS The register was read from Save State.
|
||||
@retval EFI_INVALID_PARAMTER Buffer is NULL.
|
||||
@retval EFI_UNSUPPORTED This function does not support reading Register.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesReadSaveStateRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register,
|
||||
IN UINTN Width,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
Writes an SMM Save State register on the target processor. If this function
|
||||
returns EFI_UNSUPPORTED, then the caller is responsible for writing the
|
||||
SMM Save Sate register.
|
||||
|
||||
@param[in] CpuIndex The index of the CPU to write the SMM Save State. The
|
||||
value must be between 0 and the NumberOfCpus field in
|
||||
the System Management System Table (SMST).
|
||||
@param[in] Register The SMM Save State register to write.
|
||||
@param[in] Width The number of bytes to write to the CPU save state.
|
||||
@param[in] Buffer Upon entry, this holds the new CPU register value.
|
||||
|
||||
@retval EFI_SUCCESS The register was written to Save State.
|
||||
@retval EFI_INVALID_PARAMTER Buffer is NULL.
|
||||
@retval EFI_UNSUPPORTED This function does not support writing Register.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SmmCpuFeaturesWriteSaveStateRegister (
|
||||
IN UINTN CpuIndex,
|
||||
IN EFI_SMM_SAVE_STATE_REGISTER Register,
|
||||
IN UINTN Width,
|
||||
IN CONST VOID *Buffer
|
||||
)
|
||||
{
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
/**
|
||||
This function is hook point called after the gEfiSmmReadyToLockProtocolGuid
|
||||
notification is completely processed.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
SmmCpuFeaturesCompleteSmmReadyToLock (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
This API provides a method for a CPU to allocate a specific region for storing page tables.
|
||||
|
||||
This API can be called more once to allocate memory for page tables.
|
||||
|
||||
Allocates the number of 4KB pages of type EfiRuntimeServicesData and returns a pointer to the
|
||||
allocated buffer. The buffer returned is aligned on a 4KB boundary. If Pages is 0, then NULL
|
||||
is returned. If there is not enough memory remaining to satisfy the request, then NULL is
|
||||
returned.
|
||||
|
||||
This function can also return NULL if there is no preference on where the page tables are allocated in SMRAM.
|
||||
|
||||
@param Pages The number of 4 KB pages to allocate.
|
||||
|
||||
@return A pointer to the allocated buffer for page tables.
|
||||
@retval NULL Fail to allocate a specific region for storing page tables,
|
||||
Or there is no preference on where the page tables are allocated in SMRAM.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
EFIAPI
|
||||
SmmCpuFeaturesAllocatePageTableMemory (
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
return NULL;
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
## @file
|
||||
# The CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
#
|
||||
# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
# This program and the accompanying materials
|
||||
# are licensed and made available under the terms and conditions of the BSD License
|
||||
# which accompanies this distribution. The full text of the license may be found at
|
||||
# http://opensource.org/licenses/bsd-license.php
|
||||
#
|
||||
# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = SmmCpuFeaturesLib
|
||||
MODULE_UNI_FILE = SmmCpuFeaturesLib.uni
|
||||
FILE_GUID = 34001BF4-1E93-4e08-B90E-52F2418A5026
|
||||
MODULE_TYPE = DXE_SMM_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
LIBRARY_CLASS = SmmCpuFeaturesLib
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
UefiCpuPkg/UefiCpuPkg.dec
|
||||
QuarkSocPkg/QuarkSocPkg.dec
|
||||
|
||||
[Sources]
|
||||
SmmCpuFeaturesLib.c
|
||||
|
||||
[LibraryClasses]
|
||||
QNCAccessLib
|
||||
|
@@ -0,0 +1,18 @@
|
||||
// /** @file
|
||||
// The CPU specific programming for PiSmmCpuDxeSmm module.
|
||||
//
|
||||
// Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
//
|
||||
// This program and the accompanying materials
|
||||
// are licensed and made available under the terms and conditions of the BSD License
|
||||
// which accompanies this distribution. The full text of the license may be found at
|
||||
// http://opensource.org/licenses/bsd-license.php
|
||||
//
|
||||
// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "The CPU specific programming for PiSmmCpuDxeSmm module."
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "The CPU specific programming for PiSmmCpuDxeSmm module."
|
Reference in New Issue
Block a user