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:
Michael Kinney
2015-12-15 19:22:23 +00:00
committed by mdkinney
parent 46ff196fde
commit 9b6bbcdbfd
176 changed files with 54761 additions and 0 deletions

View File

@@ -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

View 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);
}

View File

@@ -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

View 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;
}

File diff suppressed because it is too large Load Diff

View 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

View 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."

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View 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;
}

View File

@@ -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

View File

@@ -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 ();
}
}

View File

@@ -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

View File

@@ -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

View 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;
}

View 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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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."