vendorcode/amd/opensil: Add Turin OpenSIL

Add Turin OpenSIL driver and submodule pointing to turin_poc branch
of github.com/openSIL/openSIL repository.

Change-Id: Idd6d4e78a055926061de330da620c943b42a50a7
Signed-off-by: Michał Żygowski <michal.zygowski@3mdeb.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/88711
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@mailbox.org>
Reviewed-by: Felix Held <felix-coreboot@felixheld.de>
This commit is contained in:
Michał Żygowski 2025-07-08 20:46:36 +02:00 committed by Matt DeVillier
commit 4d1d27fcf3
18 changed files with 410 additions and 88 deletions

4
.gitmodules vendored
View file

@ -70,3 +70,7 @@
[submodule "3rdparty/open-power-signing-utils"]
path = 3rdparty/open-power-signing-utils
url = https://review.coreboot.org/open-power-signing-utils.git
[submodule "src/vendorcode/amd/opensil/turin_poc/opensil"]
path = src/vendorcode/amd/opensil/turin_poc/opensil
url = https://github.com/openSIL/openSIL.git
branch = turin_poc

View file

@ -68,6 +68,7 @@ config SOC_SPECIFIC_OPTIONS
select SOC_AMD_COMMON_BLOCK_USE_ESPI
select SOC_AMD_COMMON_BLOCK_XHCI
select SOC_AMD_OPENSIL
select SOC_AMD_OPENSIL_TURIN_POC
select OPENSIL_DRIVER
select DRAM_SUPPORT_DDR5
select SSE2

View file

@ -15,10 +15,17 @@ config SOC_AMD_OPENSIL_GENOA_POC
Select this on SoCs that use the Genoa proof of concept version of
openSIL.
config SOC_AMD_OPENSIL_TURIN_POC
bool
help
Select this on SoCs that use the Turin proof of concept version of
openSIL.
config AMD_OPENSIL_PATH
string "Path to openSIL source"
depends on !SOC_AMD_OPENSIL_STUB
default "$(top)/src/vendorcode/amd/opensil/genoa_poc/opensil" if SOC_AMD_OPENSIL_GENOA_POC
default "$(top)/src/vendorcode/amd/opensil/turin_poc/opensil" if SOC_AMD_OPENSIL_TURIN_POC
help
Set to the path of the openSIL directory containing meson.build.
example
@ -26,6 +33,7 @@ config AMD_OPENSIL_PATH
config AMD_OPENSIL_MPIO_CHIP_H_FILE
string "Location of specific MPIO chip.h implementation"
default "$(top)/src/vendorcode/amd/opensil/genoa_poc/mpio/chip.h" if SOC_AMD_OPENSIL_GENOA_POC
default "$(top)/src/vendorcode/amd/opensil/turin_poc/mpio/chip.h" if SOC_AMD_OPENSIL_TURIN_POC
default "$(top)/src/vendorcode/amd/opensil/stub/mpio/chip.h"
help
Set to the location of the MPIO chip.h in the selected openSIL

View file

@ -66,6 +66,36 @@ config OPENSIL_DEBUG_RAS
help
Enable printing RAS related messages.
config OPENSIL_DEBUG_MPIO
bool "Enable MPIO messages"
default y
help
Enable printing MPIO related messages.
config OPENSIL_DEBUG_CXL
bool "Enable CXL messages"
default y
help
Enable printing CXL related messages.
config OPENSIL_DEBUG_SDXI
bool "Enable SDXI messages"
default y
help
Enable printing SDXI related messages.
config OPENSIL_DEBUG_RCMGR
bool "Enable RC MGR messages"
default y
help
Enable printing Resource Manager related messages.
config OPENSIL_DEBUG_XUSL_CMN
bool "Enable xUSL CommonLib messages"
default y
help
Enable printing xUSL CommonLib related messages.
endif # OPENSIL_DEBUG_OUTPUT
endif # SOC_AMD_OPENSIL

View file

@ -15,6 +15,7 @@ endif
opensil_dir := $(call strip_quotes,$(CONFIG_AMD_OPENSIL_PATH))
subdirs-$(CONFIG_SOC_AMD_OPENSIL_GENOA_POC) += genoa_poc
subdirs-$(CONFIG_SOC_AMD_OPENSIL_TURIN_POC) += turin_poc
ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y)
cpu_family_string="x86"
@ -63,7 +64,11 @@ $(OBJPATH)/$(OPENSIL_CONFIG): $(opensil_dir)/../opensil_config.template
$< > $@
$(OBJPATH)/$(OPENSIL_CONFIG).h: $(OBJPATH)/$(OPENSIL_CONFIG) $(obj)/config.h $(objutil)/kconfig/conf
cd $(opensil_dir); KCONFIG_CONFIG=$(OBJPATH)/$(OPENSIL_CONFIG) KCONFIG_AUTOHEADER=$@ $(PYTHON) util/kconfig/lib/genconfig.py Kconfig
cd $(opensil_dir); \
KCONFIG_CONFIG=$(OBJPATH)/$(OPENSIL_CONFIG) \
KCONFIG_AUTOHEADER=$@ \
$(PYTHON) util/kconfig/lib/genconfig.py \
--config-out $(OBJPATH)/$(OPENSIL_CONFIG) Kconfig
# meson handles ccache on its own
OPENSIL_COMPILER=$(filter-out $(CCACHE), $(CC_ramstage))

View file

@ -1,5 +1,7 @@
## SPDX-License-Identifier: GPL-2.0-only
CFLAGS_opensil = -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas
subdirs-y += mpio
CPPFLAGS_common += -I$(opensil_dir)/Include -I$(opensil_dir)/xUSL -I$(opensil_dir)/xUSL/Include -I$(opensil_dir)/xUSL/FCH -I$(opensil_dir)/xUSL/FCH/Common -I$(opensil_dir)/xSIM -I$(opensil_dir)/xPRF
@ -12,7 +14,7 @@ ramstage-y += memmap.c
ramstage-y += opensil_console.c
ramstage-y += ramstage.c
$(obj)/romstage/vendorcode/amd/opensil/turin_poc/opensil_console.o: CFLAGS_romstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas
$(obj)/romstage/vendorcode/amd/opensil/turin_poc/romstage.o: CFLAGS_romstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas
$(obj)/romstage/vendorcode/amd/opensil/turin_poc/opensil_console.o: CFLAGS_romstage += $(CFLAGS_opensil)
$(obj)/romstage/vendorcode/amd/opensil/turin_poc/romstage.o: CFLAGS_romstage += $(CFLAGS_opensil)
$(obj)/ramstage/vendorcode/amd/opensil/turin_poc/opensil_console.o: CFLAGS_ramstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas
$(obj)/ramstage/vendorcode/amd/opensil/turin_poc/opensil_console.o: CFLAGS_ramstage += $(CFLAGS_opensil)

View file

@ -4,13 +4,13 @@
#include <Sil-api.h>
#include <SilCommon.h>
#include <xSIM-api.h>
#include <FCH/Common/FchCommonCfg.h>
#include <FCH/FchClass-api.h>
#include "../opensil.h"
void opensil_fill_fadt(acpi_fadt_t *fadt)
{
FCHHWACPI_INPUT_BLK *blk = SilFindStructure(SilId_FchHwAcpiP, 0);
FCHHWACPI_INPUT_BLK *blk = SilFindStructure(SilId_FchHwAcpiP, 0);
fadt->pm1a_evt_blk = blk->AcpiPm1EvtBlkAddr;
fadt->pm1a_cnt_blk = blk->AcpiPm1CntBlkAddr;

View file

@ -1,14 +1,19 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/* Keep this in sync with openSIL SilCommon.h file */
#define DEBUG_FILTER_APOB 0x00000001UL
#define DEBUG_FILTER_NBIO 0x00000002UL
#define DEBUG_FILTER_CCX 0x00000004UL
#define DEBUG_FILTER_SMU 0x00000008UL
#define DEBUG_FILTER_DF 0x00000010UL
#define DEBUG_FILTER_MEM 0x00000040UL
#define DEBUG_FILTER_FCH 0x00000080UL
#define DEBUG_FILTER_RAS 0x00000100UL
#define DEBUG_FILTER_APOB 0x00000001UL
#define DEBUG_FILTER_NBIO 0x00000002UL
#define DEBUG_FILTER_CCX 0x00000004UL
#define DEBUG_FILTER_SMU 0x00000008UL
#define DEBUG_FILTER_DF 0x00000010UL
#define DEBUG_FILTER_MPIO 0x00000020UL
#define DEBUG_FILTER_MEM 0x00000040UL
#define DEBUG_FILTER_FCH 0x00000080UL
#define DEBUG_FILTER_RAS 0x00000100UL
#define DEBUG_FILTER_CXL 0x00000200UL
#define DEBUG_FILTER_SDXI 0x00000400UL
#define DEBUG_FILTER_RCMGR 0x00000800UL
#define DEBUG_FILTER_XUSL_CMN 0x00001000UL
#define SIL_DEBUG(topic) (CONFIG(OPENSIL_DEBUG_##topic) ? DEBUG_FILTER_##topic : 0)
@ -18,6 +23,11 @@
SIL_DEBUG(CCX) | \
SIL_DEBUG(SMU) | \
SIL_DEBUG(DF) | \
SIL_DEBUG(MPIO) | \
SIL_DEBUG(MEM) | \
SIL_DEBUG(FCH) | \
SIL_DEBUG(RAS) )
SIL_DEBUG(RAS) | \
SIL_DEBUG(CXL) | \
SIL_DEBUG(SDXI) | \
SIL_DEBUG(RCMGR) | \
SIL_DEBUG(XUSL_CMN) )

View file

@ -1,8 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <SilCommon.h>
#include <Sil-api.h> // needed above ApobCmn.h
#include <ApobCmn.h>
#include <Sil-api.h>
#include <opensil_config.h> // needed above ApobCmn.h
#include <APOB/Common/ApobCmn.h>
#include <xPRF-api.h>
#include "../opensil.h"
@ -46,7 +47,7 @@ const char *opensil_get_hole_info_type(uint32_t type)
void opensil_get_hole_info(uint32_t *n_holes, uint64_t *top_of_mem, void **hole_info)
{
SIL_STATUS status = xPrfGetSystemMemoryMap(n_holes, top_of_mem, hole_info);
SIL_STATUS status = xPrfGetSystemMemoryMap(n_holes, top_of_mem, hole_info);
SIL_STATUS_report("xPrfGetSystemMemoryMap", status);
// Make sure hole_info does not get initialized to something odd by xPRF on failure
if (status != SilPass) {

View file

@ -22,6 +22,8 @@ c_args = ['-nostdinc',
'-Wno-unused-parameter',
# ubiquitous problem in openSIL
'-Wno-missing-field-initializers',
# remove after https://github.com/openSIL/openSIL/pull/39 is merged
'-Wno-unused-but-set-variable',
##CLANG_ARGS##
]

View file

@ -2,4 +2,4 @@
ramstage-y += chip.c
$(obj)/ramstage/vendorcode/amd/opensil/turin_poc/mpio/chip.o: CFLAGS_ramstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas
$(obj)/ramstage/vendorcode/amd/opensil/turin_poc/mpio/chip.o: CFLAGS_ramstage += $(CFLAGS_opensil)

View file

@ -2,18 +2,38 @@
#include <device/device.h>
#include <device/pci_def.h>
#include <opensil_config.h>
#include <CCX/Common/CcxApic.h>
#include <Cxl/CxlClass-api.h>
#include <Mpio/Common/MpioStructs.h>
#include <Mpio/MpioClass-api.h>
#include <NBIO/NbioClass-api.h>
#include <Nbio/NbioClass-api.h>
#include <RcMgr/DfX/RcManager4-api.h>
#include <vendorcode/amd/opensil/opensil.h>
#include <xSIM-api.h>
#include <static.h>
#include "chip.h"
static void mpio_params_config(void)
{
MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0);
struct device *gnb = DEV_PTR(gnb_0);
struct device *iommu = DEV_PTR(iommu_0);
struct device *psp = DEV_PTR(asp);
struct device *nbif = DEV_PTR(nbif_0);
mpio_data->CfgNbioSsid = gnb->subsystem_vendor |
((uint32_t)gnb->subsystem_device << 16);
mpio_data->CfgIommuSsid = iommu->subsystem_vendor |
((uint32_t)iommu->subsystem_device << 16);
mpio_data->CfgPspccpSsid = psp->subsystem_vendor |
((uint32_t)psp->subsystem_device << 16);
mpio_data->CfgNbifF0Ssid = nbif->subsystem_vendor |
((uint32_t)nbif->subsystem_device << 16);
mpio_data->CfgNtbSsid = 0; // Not implemented in OpenSIL
mpio_data->CfgNtbccpSsid = 0; // Not implemented in OpenSIL
mpio_data->CfgDxioClockGating = 1;
mpio_data->PcieDxioTimingControlEnable = 0;
mpio_data->PCIELinkReceiverDetectionPolling = 0;
@ -24,13 +44,12 @@ static void mpio_params_config(void)
mpio_data->DxioPhyProgramming = 1;
mpio_data->CfgSkipPspMessage = 1;
mpio_data->DxioSaveRestoreModes = 0xff;
mpio_data->AmdAllowCompliance = 0;
mpio_data->AmdAllowCompliance = 0xff;
mpio_data->AmdAllowCompliance = 0xf;
mpio_data->SrisEnableMode = 0xff;
mpio_data->SrisSkipInterval = 0;
mpio_data->SrisSkpIntervalSel = 1;
mpio_data->SrisCfgType = 0;
mpio_data->SrisAutoDetectMode = 0xff;
mpio_data->SrisAutoDetectMode = 0xf;
mpio_data->SrisAutodetectFactor = 0;
mpio_data->SrisLowerSkpOsGenSup = 0;
mpio_data->SrisLowerSkpOsRcvSup = 0;
@ -45,28 +64,21 @@ static void mpio_params_config(void)
mpio_data->SurpriseDownFeature = 1;
mpio_data->LcMultAutoSpdChgOnLastRateEnable = 0;
mpio_data->AmdRxMarginEnabled = 1;
mpio_data->CfgPcieCVTestWA = 1;
mpio_data->CfgPcieCVTestWA = 0;
mpio_data->CfgPcieAriSupport = 1;
mpio_data->CfgNbioCTOtoSC = 0;
mpio_data->CfgNbioCTOIgnoreError = 1;
mpio_data->CfgNbioSsid = 0;
mpio_data->CfgIommuSsid = 0;
mpio_data->CfgPspccpSsid = 0;
mpio_data->CfgNtbccpSsid = 0;
mpio_data->CfgNbifF0Ssid = 0;
mpio_data->CfgNtbSsid = 0;
mpio_data->AmdPcieSubsystemDeviceID = 0x1453;
mpio_data->AmdPcieSubsystemVendorID = 0x1022;
mpio_data->GppAtomicOps = 1;
mpio_data->GfxAtomicOps = 1;
mpio_data->AmdNbioReportEdbErrors = 0;
mpio_data->OpnSpare = 0;
mpio_data->AmdPreSilCtrl0 = 0;
mpio_data->MPIOAncDataSupport = 1;
mpio_data->AfterResetDelay = 0;
mpio_data->CfgEarlyLink = 0;
mpio_data->AmdCfgExposeUnusedPciePorts = 1; // Show all ports
mpio_data->CfgForcePcieGenSpeed = 0;
mpio_data->CfgForcePcieGenSpeed = 0xff;
mpio_data->CfgSataPhyTuning = 0;
mpio_data->PcieLinkComplianceModeAllPorts = 0;
mpio_data->AmdMCTPEnable = 0;
@ -79,30 +91,64 @@ static void mpio_params_config(void)
// A getter and setter, both are needed for this PCD.
mpio_data->AmdPciePresetMask32GtAllPort = 0xffffffff;
mpio_data->PcieLinkAspmAllPort = 0xff;
mpio_data->SyncHeaderByPass = 1;
mpio_data->CxlTempGen5AdvertAltPtcl = 0;
mpio_data->CfgSevSnpSupport = 0;
mpio_data->CfgSevTioSupport = 0;
mpio_data->PcieIdeCapSup = 0;
mpio_data->Master7bitSteeringTag = 1;
/* TODO handle this differently on multisocket */
mpio_data->PcieTopologyData.PlatformData[0].Flags = DESCRIPTOR_TERMINATE_LIST;
mpio_data->PcieTopologyData.PlatformData[0].PciePortList = mpio_data->PcieTopologyData.PortList;
}
static void cxl_params_config(void)
{
CXLCLASS_DATA_BLK *cxl_data = SilFindStructure(SilId_CxlClass, 0);
CXLCLASS_INPUT_BLK *input = &cxl_data->CxlInputBlock;
input->AmdPcieAerReportMechanism = 1;
}
static void nbio_params_config(void)
{
NBIOCLASS_DATA_BLOCK *nbio_data = SilFindStructure(SilId_NbioClass, 0);
NBIOCLASS_INPUT_BLK *input = &nbio_data->NbioInputBlk;
input->CfgHdAudioEnable = false;
input->EsmEnableAllRootPorts = false;
input->EsmTargetSpeed = 16;
input->CfgRxMarginPersistenceMode = 1;
input->CfgDxioFrequencyVetting = false;
input->CfgSkipPspMessage = 1;
input->CfgEarlyTrainTwoPcieLinks = false;
input->EarlyBmcLinkTraining = true;
input->EdpcEnable = 0;
input->PcieAerReportMechanism = 2;
input->SevSnpSupport = false;
NBIO_CONFIG_DATA *input = &nbio_data->NbioConfigData;
input->EsmEnableAllRootPorts = false;
input->EsmTargetSpeed = 16;
input->CfgRxMarginPersistenceMode = 1;
input->SevSnpSupport = false;
input->AerEnRccDev0 = false;
input->CfgAEREnable = true;
input->AtomicRoutingEnStrap5 = true;
input->CfgSriovEnDev0F1 = true;
input->CfgAriEnDev0F1 = true;
input->CfgAerEnDev0F1 = true;
input->CfgAcsEnDev0F1 = true;
input->CfgAtsEnDev0F1 = true;
input->CfgPasidEnDev0F1 = true;
input->CfgRtrEnDev0F1 = true;
input->CfgPriEnDev0F1 = true;
input->CfgPwrEnDev0F1 = true;
input->AtcEnable = true;
input->NbifDev0F1AtomicRequestEn = true;
input->AcsEnRccDev0 = true;
input->AcsP2pReq = true;
input->AcsSourceVal = true;
input->RccDev0E2EPrefix = true;
input->RccDev0ExtendedFmtSupported = true;
input->CfgSyshubMgcgClkGating = 1;
input->IoApicIdPreDefineEn = true;
/* Up to 16 IOAPICs for 2 sockets (8 per socket) */
input->IoApicIdBase = 240;
input->IommuAvicSupport = true;
if (CONFIG(XAPIC_ONLY) || CONFIG(X2APIC_LATE_WORKAROUND))
input->AmdApicMode = xApicMode;
else if (CONFIG(X2APIC_ONLY))
input->AmdApicMode = x2ApicMode;
else
input->AmdApicMode = ApicAutoMode;
}
static void setup_bmc_lanes(uint8_t lane, uint8_t socket)
@ -111,16 +157,11 @@ static void setup_bmc_lanes(uint8_t lane, uint8_t socket)
rc_mgr_input_block->BmcSocket = socket;
rc_mgr_input_block->EarlyBmcLinkLaneNum = lane;
NBIOCLASS_DATA_BLOCK *nbio_data = SilFindStructure(SilId_NbioClass, 0);
NBIOCLASS_INPUT_BLK *nbio_input = &nbio_data->NbioInputBlk;
nbio_input->EarlyBmcLinkSocket = socket;
nbio_input->EarlyBmcLinkLaneNum = lane;
nbio_input->EarlyBmcLinkDie = 0;
MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0);
mpio_data->EarlyBmcLinkSocket = socket;
mpio_data->EarlyBmcLinkLaneNum = lane;
mpio_data->EarlyBmcLinkDie = 0;
mpio_data->EarlyBmcLinkTraining = true;
}
void opensil_mpio_per_device_config(struct device *dev)
@ -198,5 +239,6 @@ void opensil_mpio_per_device_config(struct device *dev)
void opensil_mpio_global_config(void)
{
mpio_params_config();
cxl_params_config();
nbio_params_config();
}

View file

@ -8,13 +8,13 @@
/*
* TURIN MPIO mapping
* P0 -> [0-15]
* G0 -> [16-31]
* P3 -> [16-31]
* P1 -> [32-47]
* G1 -> [48-63]
* P2 -> [64-79]
* G2 -> [80-95]
* P3 -> [96-111]
* G3 -> [112-127]
* P2 -> [48-63]
* G1 -> [64-79]
* G3 -> [80-95]
* G0 -> [96-111]
* G2 -> [112-127]
* P4 -> [128-131]
* P5 -> [132-136]
*/

@ -0,0 +1 @@
Subproject commit a65485ffa7bddec696576323c6fc839ea5bb081d

View file

@ -2,4 +2,4 @@ CONFIG_PLAT_APOB_ADDRESS=##APOB_BASE##
CONFIG_PSP_BIOS_BIN_BASE=##BIOS_ENTRY_BASE##
CONFIG_PSP_BIOS_BIN_SIZE=##BIOS_ENTRY_SIZE##
CONFIG_PLAT_NUMBER_SOCKETS=1
CONFIG_SOC_F19M10=y
CONFIG_SOC_F1AM00=y

View file

@ -14,11 +14,13 @@ static int translate_opensil_debug_level(size_t MsgLevel)
return BIOS_ERR;
case SIL_TRACE_WARNING:
return BIOS_WARNING;
case SIL_TRACE_ENTRY:
case SIL_TRACE_EXIT:
return BIOS_SPEW;
case SIL_TRACE_INFO:
return BIOS_DEBUG;
case SIL_TRACE_ENTRY:
case SIL_TRACE_EXIT:
case SIL_TRACE_RAW:
case SIL_TRACE_VERBOSE:
return BIOS_SPEW;
default:
return BIOS_NEVER;
}
@ -32,9 +34,26 @@ void HostDebugService(size_t MsgLevel, const char *SilPrefix, const char *Messag
const int loglevel = translate_opensil_debug_level(MsgLevel);
/* print fomatted prefix */
if (CONFIG(OPENSIL_DEBUG_PREFIX))
printk(loglevel, "%s%s:%zu:", SilPrefix, Function, Line);
/* print formatted prefix */
if (CONFIG(OPENSIL_DEBUG_PREFIX)) {
switch (MsgLevel) {
case SIL_TRACE_RAW: break; // Raw print do nothing
case SIL_TRACE_ENTRY:
printk(loglevel, "%s Enter %s:%zu:", SilPrefix, Function, Line);
break;
case SIL_TRACE_EXIT:
printk(loglevel, "%s Exit %s:%zu:", SilPrefix, Function, Line);
break;
case SIL_TRACE_ERROR:
case SIL_TRACE_WARNING:
case SIL_TRACE_INFO:
case SIL_TRACE_VERBOSE:
/* fallthrough */
default:
printk(loglevel, "%s%s:%zu:", SilPrefix, Function, Line);
break;
}
}
/* print formatted message */
va_list args;

View file

@ -1,7 +1,9 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef _VENDORCODE_AND_OPENSIL_CONSOLE
#define _VENDORCODE_AND_OPENSIL_CONSOLE
#ifndef _VENDORCODE_AMD_OPENSIL_CONSOLE
#define _VENDORCODE_AMD_OPENSIL_CONSOLE
#include <types.h>
void HostDebugService(size_t MsgLevel, const char *SilPrefix, const char *Message,
const char *Function, size_t Line, ...);

View file

@ -1,13 +1,25 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#include <FCH/Common/FchCommonCfg.h>
#include <FCH/Common/FchCore/FchSata/FchSata.h>
/* opensil_config.h needed for PROJ_MAX_* defines */
#include <opensil_config.h>
#include <CCX/CcxClass-api.h>
#include <CCX/Common/CcxApic.h>
#include <DF/DfClass-api.h>
#include <FCH/FchClass-api.h>
#include <FCH/FchHwAcpi-api.h>
#include <FCH/FchIsa-api.h>
#include <FCH/Common/FchCore/FchSata/FchSataBlk.h>
#include <Mpio/MpioClass-api.h>
#include <RcMgr/DfX/RcManager4-api.h>
#include <Sdxi/SdxiClass-api.h>
#include <amdblocks/reset.h>
#include <bootstate.h>
#include <cbmem.h>
#include <cpu/cpu.h>
#include <cpu/x86/smm.h>
#include <device/device.h>
#include <soc/aoac_defs.h>
#include <soc/iomap.h>
#include <soc/soc_chip.h>
#include <static.h>
#include <stdio.h>
@ -16,6 +28,64 @@
#include "opensil_console.h"
#include "../opensil.h"
#define TURIN_USB_STRUCT_MAJOR_VERSION 0xd
#define TURIN_USB_STRUCT_MINOR_VERSION 0x13
#define TURIN_USB_PORT_PER_CONTROLLER 2
#define TURIN_USB_CONTROLLERS_PER_SOCKET 2
#define TURIN_NUM_USB_PORTS \
(TURIN_USB_PORT_PER_CONTROLLER * TURIN_USB_CONTROLLERS_PER_SOCKET)
/*
* Structures copied from Genoa POC code, because Turin POC does not define these.
* It appears the USB structures are identical for Turin and Genoa.
*/
typedef struct {
uint8_t COMPDSTUNE;
uint8_t SQRXTUNE;
uint8_t TXFSLSTUNE;
uint8_t TXPREEMPAMPTUNE;
uint8_t TXPREEMPPULSETUNE;
uint8_t TXRISETUNE;
uint8_t TXVREFTUNE;
uint8_t TXHSXVTUNE;
uint8_t TXRESTUNE;
} __packed FCH_USB20_PHY;
typedef struct {
uint8_t RX_ANA_IQ_PHASE_ADJUST;
uint8_t RX_EQ_DELTA_IQ_OVRD_EN;
uint8_t RX_EQ_DELTA_IQ_OVRD_VAL;
uint8_t RX_IQ_PHASE_ADJUST;
uint8_t TX_VBOOST_LVL_EN;
uint8_t TX_VBOOST_LVL;
uint8_t RX_VREF_CTRL_EN;
uint8_t RX_VREF_CTRL;
uint8_t TX_VBOOST_LVL_EN_X;
uint8_t TX_VBOOST_LVL_X;
uint8_t RX_VREF_CTRL_EN_X;
uint8_t RX_VREF_CTRL_X;
} __packed FCH_USB31_PHY;
typedef struct {
uint8_t Version_Major;
uint8_t Version_Minor;
uint8_t TableLength;
uint8_t Reserved0;
uint8_t Usb20PhyEnable;
FCH_USB20_PHY Usb20PhyPort[TURIN_NUM_USB_PORTS];
uint8_t Reserved1;
uint8_t S1Usb20PhyEnable;
FCH_USB20_PHY S1Usb20PhyPort[TURIN_NUM_USB_PORTS];
uint8_t Usb31PhyEnable;
FCH_USB31_PHY Usb31PhyPort[TURIN_NUM_USB_PORTS];
uint8_t S1Usb31PhyEnable;
FCH_USB31_PHY S1Usb31PhyPort[TURIN_NUM_USB_PORTS];
} __packed FCH_USB_OEM_PLATFORM_TABLE;
static FCH_USB_OEM_PLATFORM_TABLE usb_config = { 0 };
void SIL_STATUS_report(const char *function, const int status)
{
const int log_level = status == SilPass ? BIOS_DEBUG : BIOS_ERR;
@ -42,30 +112,52 @@ void SIL_STATUS_report(const char *function, const int status)
int i;
for (i = 0; i < ARRAY_SIZE(errors); i++) {
if (errors[i].status == status)
if (errors[i].status == status) {
error_string = errors[i].string;
break;
}
}
printk(log_level, "%s returned %d (%s)\n", function, status, error_string);
}
static void setup_rc_manager_default(void)
{
DFX_RCMGR_INPUT_BLK *rc_mgr_input_block = SilFindStructure(SilId_RcManager, 0);
DFX_RCMGR_INPUT_BLK *rc_mgr_input_block = SilFindStructure(SilId_RcManager, 0);
/* Let openSIL distribute the resources to the different PCI roots */
rc_mgr_input_block->SetRcBasedOnNv = false;
/* Currently 1P is the only supported configuration */
rc_mgr_input_block->SocketNumber = 1;
rc_mgr_input_block->RbsPerSocket = 4; /* PCI root bridges per socket */
rc_mgr_input_block->RbsPerSocket = 8; /* PCI root bridges per socket */
rc_mgr_input_block->McptEnable = true;
rc_mgr_input_block->PciExpressBaseAddress = CONFIG_ECAM_MMCONF_BASE_ADDRESS;
rc_mgr_input_block->BottomMmioReservedForPrimaryRb = 4ull * GiB - 32 * MiB;
rc_mgr_input_block->MmioSizePerRbForNonPciDevice = 16 * MiB;
/* MmioAbove4GLimit will be adjusted down in openSIL */
rc_mgr_input_block->MmioAbove4GLimit = POWER_OF_2(cpu_phys_address_size());
/*
* Turin has 52 bits of available physical address space without SME
* enabled. To avoid using 5-level paging (which we do not support yet
* in coreboot and UEFI payload) required to cover MMIO above 48 bits
* of address space (since 4-level paging can cover only 48 bits of
* physical address space), limit the MMIO to maximum of 48 bits.
* MmioAbove4GLimit will be adjusted down in openSIL if needed.
*/
rc_mgr_input_block->MmioAbove4GLimit = POWER_OF_2(MIN(48, cpu_phys_address_size()));
rc_mgr_input_block->Above4GMmioSizePerRbForNonPciDevice = 0;
}
static void setup_data_fabric_default(void)
{
DFCLASS_INPUT_BLK *df_input_block = SilFindStructure(SilId_DfClass, 0);
if (!df_input_block) {
printk(BIOS_ERR, "OpenSIL: Data Fabric block not found\n");
return;
}
df_input_block->AmdPciExpressBaseAddress = CONFIG_ECAM_MMCONF_BASE_ADDRESS;
}
#define NUM_XHCI_CONTROLLERS 2
static void configure_usb(void)
{
@ -73,6 +165,7 @@ static void configure_usb(void)
const struct soc_usb_config *usb = &soc_config->usb;
FCHUSB_INPUT_BLK *fch_usb_data = SilFindStructure(SilId_FchUsb, 0);
fch_usb_data->Xhci0Enable = usb->xhci0_enable;
fch_usb_data->Xhci1Enable = usb->xhci1_enable;
fch_usb_data->Xhci2Enable = false; /* there's no XHCI2 on this SoC */
@ -85,25 +178,37 @@ static void configure_usb(void)
fch_usb_data->XhciOcPolarityCfgLow = usb->polarity_cfg_low;
fch_usb_data->Usb3PortForceGen1 = usb->usb3_force_gen1.raw;
/* Instead of overwriting the whole OemUsbConfigurationTable, only copy the relevant
fields to the pre-populated data structure */
fch_usb_data->OemUsbConfigurationTable.Usb31PhyEnable = usb->usb31_phy_enable;
if (usb->usb31_phy_enable)
memcpy(&fch_usb_data->OemUsbConfigurationTable.Usb31PhyPort, usb->usb31_phy,
sizeof(fch_usb_data->OemUsbConfigurationTable.Usb31PhyPort));
fch_usb_data->OemUsbConfigurationTable.Usb31PhyEnable = usb->s1_usb31_phy_enable;
if (usb->s1_usb31_phy_enable)
memcpy(&fch_usb_data->OemUsbConfigurationTable.S1Usb31PhyPort, usb->s1_usb31_phy,
sizeof(fch_usb_data->OemUsbConfigurationTable.S1Usb31PhyPort));
memset(&usb_config, 0, sizeof(usb_config));
usb_config.Version_Major = TURIN_USB_STRUCT_MAJOR_VERSION;
usb_config.Version_Minor = TURIN_USB_STRUCT_MINOR_VERSION;
usb_config.TableLength = sizeof(FCH_USB_OEM_PLATFORM_TABLE);
usb_config.Usb31PhyEnable = usb->usb31_phy_enable;
memcpy(usb_config.Usb31PhyPort, usb->usb31_phy, sizeof(usb_config.Usb31PhyPort));
usb_config.S1Usb31PhyEnable = usb->s1_usb31_phy_enable;
memcpy(usb_config.S1Usb31PhyPort, usb->s1_usb31_phy, sizeof(usb_config.S1Usb31PhyPort));
fch_usb_data->OemUsbConfigurationTable = (uintptr_t)&usb_config;
}
#define NUM_SATA_CONTROLLERS 4
static void configure_sata(void)
{
FCHSATA_INPUT_BLK *fch_sata_data = SilFindStructure(SilId_FchSata, 0);
FCH_SATA2 *fch_sata_defaults = GetFchSataData();
FCHSATA_INPUT_BLK *fch_sata_defaults = FchSataGetInputBlk();
struct device *sata[NUM_SATA_CONTROLLERS] = {
DEV_PTR(sata_2_0),
DEV_PTR(sata_2_1),
DEV_PTR(sata_7_0),
DEV_PTR(sata_7_1)
};
for (int i = 0; i < NUM_SATA_CONTROLLERS; i++) {
fch_sata_data[i] = fch_sata_defaults[i];
fch_sata_data[i].SataAhciSsid = (sata[i])->subsystem_vendor |
((uint32_t)((sata[i])->subsystem_device) << 16);
fch_sata_data[i].SataSetMaxGen2 = false;
fch_sata_data[i].SataMsiEnable = true;
fch_sata_data[i].SataEspPort = 0xFF;
@ -115,6 +220,93 @@ static void configure_sata(void)
}
}
static void configure_fch_isa(void)
{
FCHISA_INPUT_BLK *fch_isa_data = SilFindStructure(SilId_FchIsa, 0);
struct device *lpc = DEV_PTR(lpc_bridge);
fch_isa_data->LpcConfig.LpcSsid = lpc->subsystem_vendor |
((uint32_t)lpc->subsystem_device << 16);
/* Keep defaults that were set by either EFS or coreboot */
fch_isa_data->SpiConfig.SpiSpeed = 0;
fch_isa_data->SpiConfig.SpiTpmSpeed = 0;
fch_isa_data->SpiConfig.WriteSpeed = 0;
}
#define FCH_DEV_ENABLE(dev, aoac_bit) \
fch_data->FchRunTime.FchDeviceEnableMap |= ((DEV_PTR(dev))->enabled ? aoac_bit : 0)
static void configure_fch_acpi(void)
{
FCHHWACPI_INPUT_BLK *fch_hwacpi_data = SilFindStructure(SilId_FchHwAcpiP, 0);
FCHCLASS_INPUT_BLK *fch_data = SilFindStructure(SilId_FchClass, 0);
struct device *smb = DEV_PTR(smbus);
fch_data->Smbus.SmbusSsid = smb->subsystem_vendor |
((uint32_t)smb->subsystem_device << 16);
fch_data->FchBldCfg.CfgSioPmeBaseAddress = 0;
fch_data->FchBldCfg.CfgAcpiPm1EvtBlkAddr = ACPI_PM_EVT_BLK;
fch_data->FchBldCfg.CfgAcpiPm1CntBlkAddr = ACPI_PM1_CNT_BLK;
fch_data->FchBldCfg.CfgAcpiPmTmrBlkAddr = ACPI_PM_TMR_BLK;
fch_data->FchBldCfg.CfgCpuControlBlkAddr = ACPI_CSTATE_CONTROL;
fch_data->FchBldCfg.CfgAcpiGpe0BlkAddr = ACPI_GPE0_BLK;
fch_data->FchBldCfg.CfgSmiCmdPortAddr = APM_CNT;
fch_data->CfgIoApicIdPreDefEnable = true;
fch_data->FchIoApicId = 128;
fch_data->WdtEnable = false;
/* Servers usually don't have KBC on SIO */
fch_data->Misc.NoneSioKbcSupport = true;
fch_hwacpi_data->PwrFailShadow = (CONFIG_MAINBOARD_POWER_FAILURE_STATE == 2) ?
3 : CONFIG_MAINBOARD_POWER_FAILURE_STATE;
fch_data->FchRunTime.FchDeviceEnableMap = 0;
FCH_DEV_ENABLE(i2c_0, FCH_AOAC_DEV_I2C0);
FCH_DEV_ENABLE(i2c_1, FCH_AOAC_DEV_I2C1);
FCH_DEV_ENABLE(i2c_2, FCH_AOAC_DEV_I2C2);
FCH_DEV_ENABLE(i2c_3, FCH_AOAC_DEV_I2C3);
FCH_DEV_ENABLE(i2c_4, FCH_AOAC_DEV_I2C4);
FCH_DEV_ENABLE(i2c_5, FCH_AOAC_DEV_I2C5);
FCH_DEV_ENABLE(uart_0, FCH_AOAC_DEV_UART0);
FCH_DEV_ENABLE(uart_1, FCH_AOAC_DEV_UART1);
FCH_DEV_ENABLE(uart_2, FCH_AOAC_DEV_UART2);
FCH_DEV_ENABLE(i3c_0, FCH_AOAC_DEV_I3C0);
FCH_DEV_ENABLE(i3c_1, FCH_AOAC_DEV_I3C1);
FCH_DEV_ENABLE(i3c_2, FCH_AOAC_DEV_I3C2);
FCH_DEV_ENABLE(i3c_3, FCH_AOAC_DEV_I3C3);
}
static void configure_sdxi(void)
{
MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0);
SDXICLASS_INPUT_BLK *sdxi_data = SilFindStructure(SilId_SdxiClass, 0);
mpio_data->AmdFabricSdxi = true;
sdxi_data->AmdFabricSdxi = true;
}
static void configure_ccx(void)
{
CCXCLASS_DATA_BLK *ccx_data = SilFindStructure(SilId_CcxClass, 0);
if (CONFIG(XAPIC_ONLY) || CONFIG(X2APIC_LATE_WORKAROUND))
ccx_data->CcxInputBlock.AmdApicMode = xApicMode;
else if (CONFIG(X2APIC_ONLY))
ccx_data->CcxInputBlock.AmdApicMode = x2ApicMode;
else
ccx_data->CcxInputBlock.AmdApicMode = ApicAutoMode;
ccx_data->CcxInputBlock.EnableAvx512 = 1;
ccx_data->CcxInputBlock.EnableSvmX2AVIC = 1;
ccx_data->CcxInputBlock.EnableSvmAVIC = true;
ccx_data->CcxInputBlock.AmdCStateIoBaseAddress = ACPI_CSTATE_CONTROL;
}
void setup_opensil(void)
{
const SIL_STATUS debug_ret = SilDebugSetup(HostDebugService);
@ -127,8 +319,13 @@ void setup_opensil(void)
SIL_STATUS_report("xSimAssignMemory", assign_mem_ret);
setup_rc_manager_default();
setup_data_fabric_default();
configure_ccx();
configure_fch_isa();
configure_fch_acpi();
configure_usb();
configure_sata();
configure_sdxi();
}
static void opensil_entry(SIL_TIMEPOINT timepoint)
@ -138,13 +335,13 @@ static void opensil_entry(SIL_TIMEPOINT timepoint)
switch (tp) {
case SIL_TP1:
ret = InitializeSiTp1();
ret = InitializeAMDSiTp1();
break;
case SIL_TP2:
ret = InitializeSiTp2();
ret = InitializeAMDSiTp2();
break;
case SIL_TP3:
ret = InitializeSiTp3();
ret = InitializeAMDSiTp3();
break;
default:
printk(BIOS_ERR, "Unknown openSIL timepoint\n");
@ -176,5 +373,3 @@ void opensil_xSIM_timepoint_3(void)
{
opensil_entry(SIL_TP3);
}
/* TODO: also call timepoints 2 and 3 from coreboot. Are they NOOP? */