/** @file
This file contains PSF routines for RC usage
Copyright (c) 2017, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/**
This procedure will disable CIO2 device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableCio2Device (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF1,
R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
0xFFFFFFFF,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Hide CIO2 devices PciCfgSpace at PSF level
@param[in] None
@retval None
**/
VOID
PsfHideCio2Device (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF1,
R_PCH_LP_PCR_PSF1_T0_SHDW_CAM_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
);
}
/**
Disable HDAudio device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableHdaDevice (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_AUD_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable xDCI device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableXdciDevice (
VOID
)
{
UINT16 RegOffset;
if (GetPchSeries () == PchLp) {
RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
} else {
RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_OTG_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
}
PchPcrAndThenOr32 (
PID_PSF2,
RegOffset,
~0u,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable xHCI device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableXhciDevice (
VOID
)
{
UINT16 RegOffset;
if (GetPchSeries () == PchLp) {
RegOffset = R_PCH_LP_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
} else {
RegOffset = R_PCH_H_PCR_PSF2_T0_SHDW_XHCI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
}
PchPcrAndThenOr32 (
PID_PSF2,
RegOffset,
~0u,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable SATA device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableSataDevice (
VOID
)
{
UINT16 RegOffset;
if (GetPchSeries () == PchLp) {
RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
} else {
RegOffset = R_PCH_H_PCR_PSF1_T0_SHDW_SATA_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
}
PchPcrAndThenOr32 (
PID_PSF1,
RegOffset,
~0u,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable ISH device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableIshDevice (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
~0u,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable ISH BAR1 at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableIshBar1 (
VOID
)
{
//
// Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
// ISH device BAR is 64bit wide so to disable BAR1
// at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
//
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_ISH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
(UINT32) ~0,
(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
);
}
/**
Disable GbE device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableGbeDevice (
VOID
)
{
UINT16 RegOffset;
PCH_SBI_PID PortId;
if (GetPchSeries () == PchLp) {
PortId = PID_PSF1;
RegOffset = R_PCH_LP_PCR_PSF1_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
} else {
PortId = PID_PSF3;
RegOffset = R_PCH_H_PCR_PSF3_T0_SHDW_GBE_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN;
}
PchPcrAndThenOr32 (
PortId,
RegOffset,
~0u,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable SMBUS device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableSmbusDevice (
VOID
)
{
///
/// Hide SMBUS device
/// Set PCR[PSF_3] + "AGNT_T0_SHDW_CFG_DIS"[SMBUS][0]
///
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
);
///
/// Function disable SMBUS device
/// Set PCR[PSF_3] + "AGNT_T0_SHDW_PCIEN"[SMBUS][8]
///
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_SMBUS_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable Thermal device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableThermalDevice (
VOID
)
{
///
/// Set PCR[PSF2] TRH PCIEN[8] to 1
///
PchPcrAndThenOr32 (
PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Hide Thermal device PciCfgSpace at PSF level
@param[in] None
@retval None
**/
VOID
PsfHideThermalDevice (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF2, R_PCH_PCR_PSF2_T0_SHDW_TRH_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
);
}
GLOBAL_REMOVE_IF_UNREFERENCED UINT16 mPchLpScsDevicePsfRegBase[] =
{
R_PCH_LP_PCR_PSF2_T0_SHDW_EMMC_REG_BASE,
R_PCH_LP_PCR_PSF2_T0_SHDW_SDIO_REG_BASE,
R_PCH_LP_PCR_PSF2_T0_SHDW_SDCARD_REG_BASE,
R_PCH_LP_PCR_PSF2_T0_SHDW_UFS_REG_BASE
};
/**
Disable SCS device at PSF level
@param[in] ScsDevNum SCS Device
@retval None
**/
VOID
PsfDisableScsDevice (
IN PCH_PSF_SCS_DEV_NUM ScsDevNum
)
{
if (ScsDevNum >= PchPsfMaxScsDevNum) {
ASSERT (FALSE);
}
PchPcrAndThenOr32 (
PID_PSF2,
mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Disable SCS devices BAR1 PSF level
@param[in] ScsDevNum SCS Device
@retval None
**/
VOID
PsfDisableScsBar1 (
IN PCH_PSF_SCS_DEV_NUM ScsDevNum
)
{
if (ScsDevNum >= PchPsfMaxScsDevNum) {
ASSERT (FALSE);
}
//
// Set AGNT_T0_SHDW_PCIEN[19:18] = 11b
// SCS device BAR is 64bit wide so to disable BAR1
// at PSF both BAR2 (32bit wide) and BAR3 (32bit wide) need to be disabled
//
PchPcrAndThenOr32 (
PID_PSF2,
mPchLpScsDevicePsfRegBase[ScsDevNum] + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
(UINT32) ~0,
(B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR2DIS | B_PCH_PCR_PSFX_T0_SHDW_PCIEN_BAR3DIS)
);
}
/**
Hide TraceHub ACPI devices PciCfgSpace at PSF level
@param[in] None
@retval None
**/
VOID
PsfHideTraceHubAcpiDevice (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_ACPI_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
(UINT32) ~0,
B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
);
}
/**
This procedure will hide TraceHub PciCfgSpace at PSF level
@retval None
**/
VOID
PsfHideTraceHubDevice (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
~0u,
B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS
);
}
/**
This procedure will reveal TraceHub PciCfgSpace at PSF level
@retval None
**/
VOID
PsfRevealTraceHubDevice (
VOID
)
{
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_CFG_DIS,
(UINT32) ~(B_PCH_PCR_PSFX_T0_SHDW_CFG_DIS_CFGDIS),
0
);
}
/**
This procedure will disable and hide TraceHub device at PSF level
@param[in] None
@retval None
**/
VOID
PsfDisableTraceHubDevice (
VOID
)
{
PsfHideTraceHubDevice ();
PchPcrAndThenOr32 (
PID_PSF3,
R_PCH_PCR_PSF3_T0_SHDW_TRACE_HUB_REG_BASE + R_PCH_PCR_PSFX_T0_SHDW_PCIEN,
0xFFFFFFFF,
B_PCH_PCR_PSFX_T0_SHDW_PCIEN_FUNDIS
);
}
/**
Calculates offset of PCR register where given rootport can be enabled/disabled
@param[in] RpIndex PCIe Root Port Index (0 based)
@retval Offset
**/
static UINT16
GetPsfPcieRootPortOffset (
IN UINT32 RpIndex
)
{
UINT16 RootPortReg;
if (GetPchSeries () == PchLp) {
RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
} else {
if (GetPchGeneration () == KblPch) {
RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
} else {
RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
}
}
return (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN);
}
/**
Re-enable PCIe Root Port at PSF level after it was disabled
@param[in] RpIndex PCIe Root Port Index (0 based)
@retval None
**/
VOID
PsfEnablePcieRootPort (
IN UINT32 RpIndex
)
{
ASSERT (RpIndex < GetPchMaxPciePortNum ());
PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), (UINT32)(~B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS), 0);
}
/**
Disable PCIe Root Port at PSF level
@param[in] RpIndex PCIe Root Port Index (0 based)
@retval None
**/
VOID
PsfDisablePcieRootPort (
IN UINT32 RpIndex
)
{
ASSERT (RpIndex < GetPchMaxPciePortNum ());
PchPcrAndThenOr32 (PID_PSF1, GetPsfPcieRootPortOffset (RpIndex), ~0u, B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS);
}
/**
Disable PCIe Root Port at PSF level.
This function will also perform S3 boot script programming
@param[in] RpIndex PCIe Root Port Index (0 based)
@retval None
**/
VOID
PsfDisablePcieRootPortWithS3BootScript (
IN UINT32 RpIndex
)
{
UINT16 RootPortReg;
UINT32 Data32And;
UINT32 Data32Or;
if (GetPchSeries () == PchLp) {
if (RpIndex >= PCH_LP_PCIE_MAX_ROOT_PORTS) {
ASSERT (FALSE);
return;
}
RootPortReg = R_PCH_LP_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
} else {
if (GetPchGeneration () == KblPch) {
if (RpIndex >= KBL_PCH_H_PCIE_MAX_ROOT_PORTS) {
ASSERT (FALSE);
return;
}
RootPortReg = R_KBL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
} else {
if (RpIndex >= SKL_PCH_H_PCIE_MAX_ROOT_PORTS) {
ASSERT (FALSE);
return;
}
RootPortReg = R_SKL_PCH_H_PCR_PSF1_T1_SHDW_PCIE01_REG_BASE;
}
}
Data32And = ~0u;
Data32Or = B_PCH_PCR_PSFX_T1_SHDW_PCIEN_FUNDIS;
PchPcrAndThenOr32 (
PID_PSF1,
RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN,
Data32And,
Data32Or
);
PCH_PCR_BOOT_SCRIPT_READ_WRITE (
S3BootScriptWidthUint32,
PID_PSF1, (RootPortReg - ((UINT16)RpIndex * 0x100) + R_PCH_PCR_PSFX_T1_SHDW_PCIEN),
&Data32Or,
&Data32And
);
}
/**
Program PSF grant counts for PCI express depending on controllers configuration
@param[in] Controller PCIe controller index
@param[in] ControllerConfig Port configuration of controller
@retval Status
**/
EFI_STATUS
PsfConfigurePcieGrantCounts (
UINT8 Controller,
UINT8 ControllerConfig
)
{
static CONST UINT8 DgcrPairsLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
{ { 5, 6 }, { 8, 9 }, { 11, 12 }, { 14, 15 } }, //SPA
{ { 19, 20 }, { 22, 23 }, { 25, 26 }, { 28, 29 } }, //SPB
{ { 33, 34 }, { 36, 37 }, { 39, 40 }, { 42, 43 } }, //SPC
};
static CONST UINT8 PgTgtLp [PCH_LP_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
{ 4, 5, 6, 7 }, //SPA
{ 12, 13, 14, 15 }, //SPB
{ 20, 21, 22, 23 } //SPC
};
static CONST UINT8 DgcrPairsH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS][2] = {
{ { 11, 12 }, { 14, 15 }, { 17, 18 }, { 20, 21 } }, //SPA
{ { 24, 25 }, { 27, 28 }, { 30, 31 }, { 33, 34 } }, //SPB
{ { 37, 38 }, { 40, 41 }, { 43, 44 }, { 46, 47 } }, //SPC
{ { 50, 51 }, { 53, 54 }, { 56, 57 }, { 59, 60 } }, //SPD
{ { 63, 64 }, { 66, 67 }, { 69, 70 }, { 72, 73 } }, //SPE
{ {182,183 }, {185,186 }, {188,189 }, {191,192 } } //SPF, only for KBL-H
};
static CONST UINT8 PgTgtH [KBL_PCH_H_PCIE_MAX_CONTROLLERS][PCH_PCIE_CONTROLLER_PORTS] = {
{ 0, 1, 2, 3 }, //SPA
{ 4, 5, 6, 7 }, //SPB
{ 12, 13, 14, 15 }, //SPC
{ 20, 21, 22, 23 }, //SPD
{ 28, 29, 30, 31 }, //SPE
{ 32, 33, 34, 35 } //SPF, only for KBL-H
};
static CONST UINT8 DefaultGrantCount = 4;
PCH_SERIES PchSeries;
UINT32 Dgcr0Addr;
UINT32 PgTgt0Addr;
UINT32 DgcrNo0;
UINT32 DgcrNo1;
UINT32 PgTgtNo;
UINT32 Channel;
UINT32 ChannelGrant[PCH_PCIE_CONTROLLER_PORTS];
DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts(%d) Start\n", Controller));
PchSeries = GetPchSeries ();
if (PchSeries == PchLp) {
Dgcr0Addr = R_PCH_LP_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
PgTgt0Addr = R_PCH_LP_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
} else {
if (GetPchGeneration () == KblPch) {
Dgcr0Addr = R_KBL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
PgTgt0Addr = R_KBL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
} else {
Dgcr0Addr = R_SKL_PCH_H_PSF1_DEV_GNTCNT_RELOAD_DGCR0;
PgTgt0Addr = R_SKL_PCH_H_PSF1_TARGET_GNTCNT_RELOAD_PG1_TGT0;
}
}
switch (ControllerConfig) {
case V_PCH_PCIE_STRPFUSECFG_RPC_1_1_1_1: //Pcie4x1
ChannelGrant[0] = 1;
ChannelGrant[1] = 1;
ChannelGrant[2] = 1;
ChannelGrant[3] = 1;
break;
case V_PCH_PCIE_STRPFUSECFG_RPC_2_1_1: //Pcie1x2_2x1
ChannelGrant[0] = 2;
ChannelGrant[1] = DefaultGrantCount;
ChannelGrant[2] = 1;
ChannelGrant[3] = 1;
break;
case V_PCH_PCIE_STRPFUSECFG_RPC_2_2: //Pcie2x2
ChannelGrant[0] = 2;
ChannelGrant[1] = DefaultGrantCount;
ChannelGrant[2] = 2;
ChannelGrant[3] = DefaultGrantCount;
break;
case V_PCH_PCIE_STRPFUSECFG_RPC_4: //Pcie1x4
ChannelGrant[0] = 4;
ChannelGrant[1] = DefaultGrantCount;
ChannelGrant[2] = DefaultGrantCount;
ChannelGrant[3] = DefaultGrantCount;
break;
default:
ASSERT (FALSE);
return EFI_INVALID_PARAMETER;
}
for (Channel = 0; Channel < PCH_PCIE_CONTROLLER_PORTS; ++Channel) {
if (PchSeries == PchLp) {
DgcrNo0 = DgcrPairsLp[Controller][Channel][0];
DgcrNo1 = DgcrPairsLp[Controller][Channel][1];
PgTgtNo = PgTgtLp[Controller][Channel];
} else {
DgcrNo0 = DgcrPairsH[Controller][Channel][0];
DgcrNo1 = DgcrPairsH[Controller][Channel][1];
PgTgtNo = PgTgtH[Controller][Channel];
}
DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo0, ChannelGrant[Channel]));
PchPcrAndThenOr32 (
PID_PSF1,
(UINT16) (Dgcr0Addr + (DgcrNo0 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
(UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
ChannelGrant[Channel]
);
DEBUG ((DEBUG_INFO, "DGCR%d = %d\n", DgcrNo1, ChannelGrant[Channel]));
PchPcrAndThenOr32 (
PID_PSF1,
(UINT16) (Dgcr0Addr + (DgcrNo1 * S_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR)),
(UINT32) ~B_PCH_PSF_DEV_GNTCNT_RELOAD_DGCR_GNT_CNT_RELOAD,
ChannelGrant[Channel]
);
DEBUG ((DEBUG_INFO, "PG1_TGT%d = %d\n", PgTgtNo, ChannelGrant[Channel]));
PchPcrAndThenOr32 (
PID_PSF1,
(UINT16) (PgTgt0Addr + (PgTgtNo * S_PCH_PSF_TARGET_GNTCNT_RELOAD)),
(UINT32) ~B_PCH_PSF_TARGET_GNTCNT_RELOAD_GNT_CNT_RELOAD,
ChannelGrant[Channel]
);
}
DEBUG ((DEBUG_INFO, "PsfConfigurePcieGrantCounts() End\n"));
return EFI_SUCCESS;
}
/**
Disable ISM NP Completion Tracking for GbE PSF port
@param[in] None
@retval None
**/
VOID
PsfDisableIsmNpCompletionTrackForGbe (
VOID
)
{
UINT16 RegOffset;
PCH_SBI_PID PortId;
if (GetPchSeries () == PchLp) {
PortId = PID_PSF1;
RegOffset = R_PCH_LP_PCR_PSF1_PSF_PORT_CONFIG_PG1_PORT7;
} else {
PortId = PID_PSF3;
RegOffset = R_PCH_H_PCR_PSF3_PSF_PORT_CONFIG_PG1_PORT1;
}
///
/// Clear PCR PSF_x_PSF_PORT_CONFIG_PGx_PORTx[5] = 0b
///
PchPcrAndThenOr8 (
PortId,
RegOffset,
(UINT8) ~(BIT5),
0
);
}
/**
Program PSF EOI Multicast configuration
@param[in] None
@retval None
**/
VOID
PsfSetEoiMulticastConfiguration (
VOID
)
{
UINT32 McastTarget;
///
/// Program PSF Multicast registers accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
///
if (GetPchSeries () == PchLp) {
McastTarget = V_PCH_LP_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
///
/// Set PCR[PSF1] + 4060h = 38A00h
///
PchPcrWrite32 (
PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
McastTarget
);
///
/// Set PCR[PSF1] + 4050h[7:0] = 11b
///
PchPcrWrite32 (
PID_PSF1, R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
0x3
);
} else {
McastTarget = V_PCH_H_PCR_PSFX_PSF_MC_AGENT_MCAST_TGT_P2SB;
if (GetPchGeneration () == KblPch) {
///
/// Set PCR[PSF1] + 405Ch = 38B00h
///
PchPcrWrite32 (
PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
McastTarget
);
///
/// Set PCR[PSF1] + 404Ch[7:0] = 11b
///
PchPcrWrite32 (
PID_PSF1, R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
0x3
);
} else {
///
/// Set PCR[PSF1] + 4058h = 38B00h
///
PchPcrWrite32 (
PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI,
McastTarget
);
///
/// Set PCR[PSF1] + 4048h[7:0] = 11b
///
PchPcrWrite32 (
PID_PSF1, R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI,
0x3
);
}
}
///
/// Set PCR[PSF1] + 4054h to P2SB target
///
PchPcrWrite32 (
PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_AGENT_MCAST0_TGT0_EOI,
McastTarget
);
///
/// Set PCR[PSF3] + 404Ch[7:0] = 11b
///
PchPcrWrite32 (
PID_PSF3, R_PCH_PCR_PSF3_PSF_MC_CONTROL_MCAST0_EOI,
0x3
);
}
/**
This function enables EOI message forwarding in PSF for PCIe ports
for cases where IOAPIC is present behind this root port.
@param[in] RpIndex Root port index (0 based)
@retval Status
**/
EFI_STATUS
PsfConfigurEoiForPciePort (
IN UINT32 RpIndex
)
{
UINT32 Data32;
UINT8 NumMcVal;
UINT32 RpDestId;
///
/// PCH-LP:
/// RP Destination ID RP Destination ID
/// 1 0x18100 7 0x18302
/// 2 0x18101 8 0x18303
/// 3 0x18102 9 0x18500
/// 4 0x18103 10 0x18501
/// 5 0x18300 11 0x18502
/// 6 0x18301 12 0x18503
///
static UINT32 PchSklLpRpDestId[PCH_LP_PCIE_MAX_ROOT_PORTS] =
{
0x18100, 0x18101, 0x18102, 0x18103, 0x18300,
0x18301, 0x18302, 0x18303, 0x18500, 0x18501,
0x18502, 0x18503
};
///
/// PCH-H:
/// RP Destination ID RP Destination ID
/// 1 0x18000 11 0x18302
/// 2 0x18001 12 0x18303
/// 3 0x18002 13 0x18500
/// 4 0x18003 14 0x18501
/// 5 0x18100 15 0x18502
/// 6 0x18101 16 0x18503
/// 7 0x18102 17 0x18700
/// 8 0x18103 18 0x18701
/// 9 0x18300 19 0x18702
/// 10 0x18301 20 0x18703
///
/// KBL-H: same as SKL-H plus the following 4 ports
/// 21 0x18800 23 0x18802
/// 22 0x18801 24 0x18803
///
static UINT32 PchHRpDestId[KBL_PCH_H_PCIE_MAX_ROOT_PORTS] =
{
0x18000, 0x18001, 0x18002, 0x18003,
0x18100, 0x18101, 0x18102, 0x18103,
0x18300, 0x18301, 0x18302, 0x18303,
0x18500, 0x18501, 0x18502, 0x18503,
0x18700, 0x18701, 0x18702, 0x18703,
0x18800, 0x18801, 0x18802, 0x18803
};
PCH_SERIES PchSeries;
PCH_GENERATION PchGen;
UINT16 PsfReg;
ASSERT (RpIndex < GetPchMaxPciePortNum ());
PchSeries = GetPchSeries ();
PchGen = GetPchGeneration ();
///
/// If there is an IOAPIC discovered behind root port program PSF Multicast registers
/// accordingly to SKL PCH BWG 5.14.4 PSF EOI Multicast Configuration
///
///
///
///
/// Read PSF_1_PSF_MC_CONTROL_MCAST0_RS0_EOI bit [7:1], increase it by 1, write back
///
if (PchSeries == PchLp) {
PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
} else {
if (PchGen == KblPch) {
PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
} else {
PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_CONTROL_MCAST0_EOI;
}
}
PchPcrRead32 (PID_PSF1, PsfReg, &Data32);
NumMcVal = (UINT8) (Data32 >> 1);
Data32 += 0x2;
PchPcrWrite32 (PID_PSF1, PsfReg, Data32);
///
/// Program PSF_1_PSF_MC_AGENT_MCAST0_RS0_TGT_EOI, the next empty register,
/// where x is the same as the value read in step 1 before the increment.
/// Program this register according to the RP# and the table below
///
if (PchSeries == PchLp) {
PsfReg = R_PCH_LP_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
RpDestId = PchSklLpRpDestId[RpIndex];
} else {
if (PchGen == KblPch) {
PsfReg = R_KBL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
} else {
PsfReg = R_SKL_PCH_H_PCR_PSF1_PSF_MC_AGENT_MCAST0_TGT0_EOI;
}
RpDestId = PchHRpDestId[RpIndex];
}
PchPcrAndThenOr32 (
PID_PSF1, PsfReg + (NumMcVal * 4),
(UINT32) ~0,
RpDestId
);
return EFI_SUCCESS;
}
/**
Reload default RP PSF device number and function number.
The PSF register doesn't got reset after system reset, which will result in mismatch between
PSF register setting and PCIE PCR PCD register setting. Reset PSF register in early phase
to avoid cycle decoding confusing.
@param[in] None
@retval Status
**/
VOID
PsfReloadDefaultPcieRpDevFunc (
VOID
)
{
UINT16 Psf1RpFuncCfgBase;
UINTN PortIndex;
UINTN MaxPciePorts;
PortIndex = 0;
MaxPciePorts = GetPchMaxPciePortNum ();
if (GetPchSeries () == PchLp) {
Psf1RpFuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
} else {
if (GetPchGeneration () == KblPch) {
Psf1RpFuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
} else {
Psf1RpFuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
}
}
//
// Reload D28 registers
//
for (; PortIndex < 8; PortIndex++) {
PchPcrWrite32 (
PID_PSF1,
Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
(PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_1 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
);
}
//
// Reload D29 registers
//
for (; PortIndex < 16 && PortIndex < MaxPciePorts; PortIndex++) {
PchPcrWrite32 (
PID_PSF1,
Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
(PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_2 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
);
}
//
// Reload D27 registers
//
for (; PortIndex < MaxPciePorts; PortIndex++) {
PchPcrWrite32 (
PID_PSF1,
Psf1RpFuncCfgBase + 4 * (UINT16) PortIndex,
(PCI_DEVICE_NUMBER_PCH_PCIE_DEVICE_3 << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_DEVICE) +
((PortIndex % 8) << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
);
}
}
/**
Assign new function number for PCIe Port Number.
This function will also perform S3 boot script programming
@param[in] RpIndex PCIe Root Port Index (0 based)
@param[in] NewFunction New Function number
@retval None
**/
VOID
PsfSetPcieFunctionWithS3BootScript (
IN UINT32 RpIndex,
IN UINT32 NewFunction
)
{
UINT16 PsfRpFuncCfgBase;
UINT16 PsfD28F0FuncCfgBase;
UINT32 Data32;
if (GetPchSeries () == PchLp) {
PsfD28F0FuncCfgBase = R_PCH_LP_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
} else {
if (GetPchGeneration () == KblPch) {
PsfD28F0FuncCfgBase = R_KBL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
} else {
PsfD28F0FuncCfgBase = R_SKL_PCH_H_PCR_PSF1_T1_AGENT_FUNCTION_CONFIG_SPA_D28_F0;
}
}
PsfRpFuncCfgBase = PsfD28F0FuncCfgBase + 4 * (UINT16)RpIndex;
//
// Program PSF1 RP function config register.
//
PchPcrAndThenOr32 (
PID_PSF1,
PsfRpFuncCfgBase,
(UINT32) ~B_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION,
(UINT32) (NewFunction << N_PCH_PCR_PSFX_TX_AGENT_FUNCTION_CONFIG_FUNCTION)
);
PchPcrRead32 (PID_PSF1, PsfRpFuncCfgBase, &Data32);
PCH_PCR_BOOT_SCRIPT_WRITE (
S3BootScriptWidthUint32,
PID_PSF1,
PsfRpFuncCfgBase,
1,
&Data32
);
}
/**
This function enables PCIe Relaxed Order in PSF
@param[in] None
@retval None
**/
VOID
PsfEnablePcieRelaxedOrder (
VOID
)
{
///
/// PCH BIOS Spec Section 8.2.9
///
PchPcrAndThenOr32 (
PID_PSF1,
R_PCH_PCR_PSF_PORT_CONFIG_PG0_PORT0,
~0u,
BIT1
);
}
/**
Configure PSF power management.
Must be called after all PSF configuration is completed.
@param[in] None
@retval None
**/
VOID
PsfConfigurePowerManagement (
VOID
)
{
PchPcrAndThenOr32 (PID_PSF1, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENTCG);
PchPcrAndThenOr32 (PID_PSF2, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
PchPcrAndThenOr32 (PID_PSF3, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
PchPcrAndThenOr32 (PID_PSF4, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
PchPcrAndThenOr32 (PID_CSME_PSF, R_PCH_PCR_PSF_GLOBAL_CONFIG, ~0u, B_PCH_PCR_PSF_GLOBAL_CONFIG_ENLCG);
}
/**
Enable VTd support in PSF.
@param[in] None
@retval None
**/
VOID
PchPsfEnableVtd (
VOID
)
{
STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
UINTN PsfPidIndex;
for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
PchPcrAndThenOr32 (
PsfPidTable[PsfPidIndex],
R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
~0u,
B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_VTDEN
);
}
}
/**
Disable PSF address-based peer-to-peer decoding.
**/
VOID
PchPsfDisableP2pDecoding (
VOID
)
{
STATIC PCH_SBI_PID PsfPidTable[] = {PID_PSF1, PID_PSF2, PID_PSF3, PID_PSF4};
UINTN PsfPidIndex;
for (PsfPidIndex = 0; PsfPidIndex < (sizeof (PsfPidTable) / sizeof (PsfPidTable[0])); PsfPidIndex++) {
PchPcrAndThenOr32 (
PsfPidTable[PsfPidIndex],
R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS0,
(UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
0
);
PchPcrAndThenOr32 (
PsfPidTable[PsfPidIndex],
R_PCH_PCR_PSF_ROOTSPACE_CONFIG_RS1,
(UINT32)~B_PCH_PCR_PSF_ROOTSPACE_CONFIG_RSX_ENADDRP2P,
0
);
}
}