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