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