From a616a589a236147fac24f1ac718afab11f2bc035 Mon Sep 17 00:00:00 2001 From: Alicja Michalska Date: Sun, 1 Mar 2026 00:40:09 +0100 Subject: [PATCH] vc/amd/opensil: Add Phoenix OpenSIL POC directory as a copy of Genoa Based on genoa_poc, this patch adds directory structure for Phoenix OpenSIL as well as git submodule needed to build it. Subsequent patches will begin adjusting this directory to Phoenix (Zen4) silicon. Change-Id: I04de276c1567c20d1e852efe220efa8131f53843 Signed-off-by: Alicja Michalska Reviewed-on: https://review.coreboot.org/c/coreboot/+/91480 Reviewed-by: Angel Pons Reviewed-by: Matt DeVillier Tested-by: build bot (Jenkins) --- .gitmodules | 5 + src/vendorcode/amd/opensil/Kconfig | 8 + src/vendorcode/amd/opensil/Makefile.mk | 1 + .../amd/opensil/phoenix_poc/Makefile.mk | 18 ++ src/vendorcode/amd/opensil/phoenix_poc/acpi.c | 24 +++ .../amd/opensil/phoenix_poc/filter.h | 23 ++ .../amd/opensil/phoenix_poc/memmap.c | 57 +++++ .../opensil/phoenix_poc/meson_cross.template | 35 +++ .../amd/opensil/phoenix_poc/mpio/Makefile.mk | 5 + .../amd/opensil/phoenix_poc/mpio/chip.c | 202 ++++++++++++++++++ .../amd/opensil/phoenix_poc/mpio/chip.h | 71 ++++++ .../amd/opensil/phoenix_poc/opensil | 1 + .../phoenix_poc/opensil_config.template | 5 + .../amd/opensil/phoenix_poc/opensil_console.c | 44 ++++ .../amd/opensil/phoenix_poc/opensil_console.h | 9 + .../amd/opensil/phoenix_poc/ramstage.c | 180 ++++++++++++++++ .../amd/opensil/phoenix_poc/romstage.c | 17 ++ 17 files changed, 705 insertions(+) create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/Makefile.mk create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/acpi.c create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/filter.h create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/memmap.c create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/meson_cross.template create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/mpio/Makefile.mk create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.c create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.h create mode 160000 src/vendorcode/amd/opensil/phoenix_poc/opensil create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/opensil_config.template create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/opensil_console.c create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/opensil_console.h create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/ramstage.c create mode 100644 src/vendorcode/amd/opensil/phoenix_poc/romstage.c diff --git a/.gitmodules b/.gitmodules index 7a8d618619..dcb6541191 100644 --- a/.gitmodules +++ b/.gitmodules @@ -70,7 +70,12 @@ [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/phoenix_poc/opensil"] + path = src/vendorcode/amd/opensil/phoenix_poc/opensil + url = https://github.com/openSIL/openSIL.git + branch = phoenix_poc [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 + diff --git a/src/vendorcode/amd/opensil/Kconfig b/src/vendorcode/amd/opensil/Kconfig index 735d6e1feb..580ea83159 100644 --- a/src/vendorcode/amd/opensil/Kconfig +++ b/src/vendorcode/amd/opensil/Kconfig @@ -15,6 +15,12 @@ config SOC_AMD_OPENSIL_GENOA_POC Select this on SoCs that use the Genoa proof of concept version of openSIL. +config SOC_AMD_OPENSIL_PHOENIX_POC + bool + help + Select this on SoCs that use the Phoenix proof of concept version of + openSIL. + config SOC_AMD_OPENSIL_TURIN_POC bool help @@ -25,6 +31,7 @@ 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/phoenix_poc/opensil" if SOC_AMD_OPENSIL_PHOENIX_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. @@ -33,6 +40,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/phoenix_poc/mpio/chip.h" if SOC_AMD_OPENSIL_PHOENIX_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 diff --git a/src/vendorcode/amd/opensil/Makefile.mk b/src/vendorcode/amd/opensil/Makefile.mk index beebaf5782..751e6ebf4b 100644 --- a/src/vendorcode/amd/opensil/Makefile.mk +++ b/src/vendorcode/amd/opensil/Makefile.mk @@ -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_PHOENIX_POC) += phoenix_poc subdirs-$(CONFIG_SOC_AMD_OPENSIL_TURIN_POC) += turin_poc ifeq ($(CONFIG_ARCH_RAMSTAGE_X86_32),y) diff --git a/src/vendorcode/amd/opensil/phoenix_poc/Makefile.mk b/src/vendorcode/amd/opensil/phoenix_poc/Makefile.mk new file mode 100644 index 0000000000..5d36d56f93 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/Makefile.mk @@ -0,0 +1,18 @@ +## SPDX-License-Identifier: GPL-2.0-only + +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 + +romstage-y += opensil_console.c +romstage-y += romstage.c + +ramstage-y += acpi.c +ramstage-y += memmap.c +ramstage-y += opensil_console.c +ramstage-y += ramstage.c + +$(obj)/romstage/vendorcode/amd/opensil/phoenix_poc/opensil_console.o: CFLAGS_romstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas +$(obj)/romstage/vendorcode/amd/opensil/phoenix_poc/romstage.o: CFLAGS_romstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas + +$(obj)/ramstage/vendorcode/amd/opensil/phoenix_poc/opensil_console.o: CFLAGS_ramstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas diff --git a/src/vendorcode/amd/opensil/phoenix_poc/acpi.c b/src/vendorcode/amd/opensil/phoenix_poc/acpi.c new file mode 100644 index 0000000000..fcdf167c12 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/acpi.c @@ -0,0 +1,24 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include + +#include "../opensil.h" + +void opensil_fill_fadt(acpi_fadt_t *fadt) +{ + FCHHWACPI_INPUT_BLK *blk = SilFindStructure(SilId_FchHwAcpiP, 0); + + fadt->pm1a_evt_blk = blk->AcpiPm1EvtBlkAddr; + fadt->pm1a_cnt_blk = blk->AcpiPm1CntBlkAddr; + fadt->pm_tmr_blk = blk->AcpiPmTmrBlkAddr; + fadt->gpe0_blk = blk->AcpiGpe0BlkAddr; +} + +unsigned long add_opensil_acpi_table(unsigned long current, acpi_rsdp_t *rsdp) +{ + return current; +} diff --git a/src/vendorcode/amd/opensil/phoenix_poc/filter.h b/src/vendorcode/amd/opensil/phoenix_poc/filter.h new file mode 100644 index 0000000000..f0817f7502 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/filter.h @@ -0,0 +1,23 @@ +/* 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 SIL_DEBUG(topic) (CONFIG(OPENSIL_DEBUG_##topic) ? DEBUG_FILTER_##topic : 0) + +#define SIL_DEBUG_MODULE_FILTER ( \ + SIL_DEBUG(APOB) | \ + SIL_DEBUG(NBIO) | \ + SIL_DEBUG(CCX) | \ + SIL_DEBUG(SMU) | \ + SIL_DEBUG(DF) | \ + SIL_DEBUG(MEM) | \ + SIL_DEBUG(FCH) | \ + SIL_DEBUG(RAS) ) diff --git a/src/vendorcode/amd/opensil/phoenix_poc/memmap.c b/src/vendorcode/amd/opensil/phoenix_poc/memmap.c new file mode 100644 index 0000000000..eed1be7e5f --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/memmap.c @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include // needed above ApobCmn.h +#include +#include + +#include "../opensil.h" + +_Static_assert(sizeof(uint32_t) == sizeof(((MEMORY_HOLE_DESCRIPTOR){0}).Type), + "Unexpected size of MEMORY_HOLE_TYPES in the MEMORY_HOLE_DESCRIPTOR " + "struct which doesn't match the code in drivers/amd/opensil/memmap.c"); + +const char *opensil_get_hole_info_type(uint32_t type) +{ + const struct hole_type { + MEMORY_HOLE_TYPES type; + const char *string; + } types[] = { + {UMA, "UMA"}, + {MMIO, "MMIO"}, + {PrivilegedDRAM, "PrivilegedDRAM"}, + {Reserved1TbRemap, "Reserved1TbRemap"}, + {ReservedSLink, "ReservedSLink"}, + {ReservedSLinkAlignment, "ReservedSLinkAlignment"}, + {ReservedDrtm, "ReservedDrtm"}, + {ReservedCvip, "ReservedCvip"}, + {ReservedSmuFeatures, "ReservedSmuFeatures"}, + {ReservedFwtpm, "ReservedFwtpm"}, + {ReservedMpioC20, "ReservedMpioC20"}, + {ReservedNbif, "ReservedNbif"}, + {ReservedCxl, "ReservedCxl"}, + {ReservedCxlAlignment, "ReservedCxlAlignment"}, + {ReservedCpuTmr, "ReservedCpuTmr"}, + {ReservedRasEinj, "ReservedRasEinj"}, + {MaxMemoryHoleTypes, "MaxMemoryHoleTypes"}, + }; + + int i; + MEMORY_HOLE_TYPES enum_type = (MEMORY_HOLE_TYPES)type; // Cast int to enum + for (i = 0; i < ARRAY_SIZE(types); i++) + if (enum_type == types[i].type) + return types[i].string; + return "Unknown 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_report("xPrfGetSystemMemoryMap", status); + // Make sure hole_info does not get initialized to something odd by xPRF on failure + if (status != SilPass) { + *hole_info = NULL; + *n_holes = 0; + *top_of_mem = 0; + } +} diff --git a/src/vendorcode/amd/opensil/phoenix_poc/meson_cross.template b/src/vendorcode/amd/opensil/phoenix_poc/meson_cross.template new file mode 100644 index 0000000000..6473b65225 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/meson_cross.template @@ -0,0 +1,35 @@ +[binaries] +c = '##COMPILER##' +ar = '##AR##' +nasm = '##NASM##' + +[built-in options] +c_args = ['-nostdinc', + '-I##OBJPATH##', + '-I##COREBOOT_DIR##/src/include', + '-I##COREBOOT_DIR##/src/arch/x86/include', + '-I##COREBOOT_DIR##/src/commonlib/include', + '-I##COREBOOT_DIR##/src/commonlib/bsd/include', + '-include', '##COREBOOT_DIR##/src/include/kconfig.h', + '-include', '##OBJPATH##/config.h', + '-include', '##COREBOOT_DIR##/src/commonlib/bsd/include/commonlib/bsd/compiler.h', + '-include', '##OPENSIL_DIR##/../filter.h', + '-DHAS_STRING_H=1', + # openSIL isn't compatible with coreboot's assert implementation, so use special case + '-D_PORTING_H_=1', + '-DSIL_DEBUG_ENABLE=##SIL_DEBUG_ENABLE##', + # openSIL uses coreboot assert which uses printk which warns about unused-param + '-Wno-unused-parameter', + # ubiquitous problem in openSIL + '-Wno-missing-field-initializers', + ##CLANG_ARGS## + ] + +[host_machine] +system = 'linux' +cpu_family = '##CPU_FAMILY##' +cpu = '##CPU##' +endian = 'little' + +[properties] +is32bit = ##IS32BIT## diff --git a/src/vendorcode/amd/opensil/phoenix_poc/mpio/Makefile.mk b/src/vendorcode/amd/opensil/phoenix_poc/mpio/Makefile.mk new file mode 100644 index 0000000000..523ebe73c8 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/mpio/Makefile.mk @@ -0,0 +1,5 @@ +## SPDX-License-Identifier: GPL-2.0-only + +ramstage-y += chip.c + +$(obj)/ramstage/vendorcode/amd/opensil/phoenix_poc/mpio/chip.o: CFLAGS_ramstage += -D_MSC_EXTENSIONS=0 -DHAS_STRING_H=1 -Wno-unknown-pragmas diff --git a/src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.c b/src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.c new file mode 100644 index 0000000000..587ab81e02 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.c @@ -0,0 +1,202 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "chip.h" + +static void mpio_params_config(void) +{ + MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0); + mpio_data->CfgDxioClockGating = 1; + mpio_data->PcieDxioTimingControlEnable = 0; + mpio_data->PCIELinkReceiverDetectionPolling = 0; + mpio_data->PCIELinkResetToTrainingTime = 0; + mpio_data->PCIELinkL0Polling = 0; + mpio_data->PCIeExactMatchEnable = 0; + mpio_data->DxioPhyValid = 1; + mpio_data->DxioPhyProgramming = 1; + mpio_data->CfgSkipPspMessage = 1; + mpio_data->DxioSaveRestoreModes = 0xff; + mpio_data->AmdAllowCompliance = 0; + mpio_data->AmdAllowCompliance = 0xff; + mpio_data->SrisEnableMode = 0xff; + mpio_data->SrisSkipInterval = 0; + mpio_data->SrisSkpIntervalSel = 1; + mpio_data->SrisCfgType = 0; + mpio_data->SrisAutoDetectMode = 0xff; + mpio_data->SrisAutodetectFactor = 0; + mpio_data->SrisLowerSkpOsGenSup = 0; + mpio_data->SrisLowerSkpOsRcvSup = 0; + mpio_data->AmdCxlOnAllPorts = 1; + mpio_data->CxlCorrectableErrorLogging = 1; + mpio_data->CxlUnCorrectableErrorLogging = 1; + // This is also available in Nbio. How to handle duplicate entries? + mpio_data->CfgAEREnable = 1; + mpio_data->CfgMcCapEnable = 0; + mpio_data->CfgRcvErrEnable = 0; + mpio_data->EarlyBmcLinkTraining = 1; + mpio_data->SurpriseDownFeature = 1; + mpio_data->LcMultAutoSpdChgOnLastRateEnable = 0; + mpio_data->AmdRxMarginEnabled = 1; + mpio_data->CfgPcieCVTestWA = 1; + 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->CfgSataPhyTuning = 0; + mpio_data->PcieLinkComplianceModeAllPorts = 0; + mpio_data->AmdMCTPEnable = 0; + mpio_data->SbrBrokenLaneAvoidanceSup = 1; + mpio_data->AutoFullMarginSup = 1; + // A getter and setter, both are needed for this PCD. + mpio_data->AmdPciePresetMask8GtAllPort = 0xffffffff; + // A getter and setter, both are needed for this PCD. + mpio_data->AmdPciePresetMask16GtAllPort = 0xffffffff; + // 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; + + /* 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 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; +} + +static void setup_bmc_lanes(uint8_t lane, uint8_t socket) +{ + DFX_RCMGR_INPUT_BLK *rc_mgr_input_block = SilFindStructure(SilId_RcManager, 0); + 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; +} + +void opensil_mpio_per_device_config(struct device *dev) +{ + /* Cache *mpio_data from SilFindStructure */ + static MPIOCLASS_INPUT_BLK *mpio_data = NULL; + if (mpio_data == NULL) { + mpio_data = SilFindStructure(SilId_MpioClass, 0); + } + + static uint32_t slot_num; + const uint32_t domain = dev_get_domain_id(dev); + const uint32_t devfn = dev->path.pci.devfn; + const struct drivers_amd_opensil_mpio_config *const config = dev->chip_info; + printk(BIOS_DEBUG, "Setting MPIO port for domain 0x%x, PCI %d:%d\n", + domain, PCI_SLOT(devfn), PCI_FUNC(devfn)); + + if (config->type == IFTYPE_UNUSED) { + if (is_dev_enabled(dev)) { + printk(BIOS_WARNING, "Unused MPIO chip, disabling PCI device.\n"); + dev->enabled = false; + } else { + printk(BIOS_DEBUG, "Unused MPIO chip, skipping.\n"); + } + return; + } + + if (config->bmc) { + setup_bmc_lanes(config->start_lane, 0); // TODO support multiple sockets + return; + } + + static int mpio_port = 0; + MPIO_PORT_DESCRIPTOR port = { .Flags = DESCRIPTOR_TERMINATE_LIST }; + if (config->type == IFTYPE_PCIE) { + const MPIO_ENGINE_DATA engine_data = + MPIO_ENGINE_DATA_INITIALIZER(MpioPcieEngine, + config->start_lane, config->end_lane, + config->hotplug == HotplugDisabled ? 0 : 1, + config->gpio_group); + port.EngineData = engine_data; + const MPIO_PORT_DATA port_data = + MPIO_PORT_DATA_INITIALIZER_PCIE(is_dev_enabled(dev) ? + MpioPortEnabled : MpioPortDisabled, + PCI_SLOT(devfn), + PCI_FUNC(devfn), + config->hotplug, + config->speed, + 0, // No backup PCIe speed + config->aspm, + config->aspm_l1_1, + config->aspm_l1_2, + config->clock_pm); + port.Port = port_data; + } else if (config->type == IFTYPE_SATA) { + const MPIO_ENGINE_DATA engine_data = + MPIO_ENGINE_DATA_INITIALIZER(MpioSATAEngine, + config->start_lane, config->end_lane, + 0, // meaningless field + config->gpio_group); + port.EngineData = engine_data; + const MPIO_PORT_DATA port_data = { .PortPresent = 1 }; + port.Port = port_data; + + } + port.Port.AlwaysExpose = 1; + port.Port.SlotNum = ++slot_num; + mpio_data->PcieTopologyData.PortList[mpio_port] = port; + /* Update TERMINATE list */ + if (mpio_port > 0) + mpio_data->PcieTopologyData.PortList[mpio_port - 1].Flags = 0; + mpio_port++; +} + +void opensil_mpio_global_config(void) +{ + mpio_params_config(); + nbio_params_config(); +} diff --git a/src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.h b/src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.h new file mode 100644 index 0000000000..0e0e160ce2 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/mpio/chip.h @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef OPENSIL_PHOENIX_POC_MPIO_CHIP_H +#define OPENSIL_PHOENIX_POC_MPIO_CHIP_H + +#include + +/* + * PHOENIX MPIO mapping + * P0 -> [0-15] + * G0 -> [16-31] + * P1 -> [32-47] + * G1 -> [48-63] + * P2 -> [64-79] + * G2 -> [80-95] + * P3 -> [96-111] + * G3 -> [112-127] + * P4 -> [128-131] + * P5 -> [132-136] + */ + +enum mpio_type { + IFTYPE_UNUSED, + IFTYPE_PCIE, + IFTYPE_SATA, +}; + +/* Sync with PCIE_HOTPLUG_TYPE */ +enum mpio_hotplug { + HotplugDisabled, ///< Hotplug disable + Basic, ///< Basic Hotplug + ServerExpress, ///< Server Hotplug Express Module + Enhanced, ///< Enhanced + Inboard, ///< Inboard + ServerEntSSD, ///< Server Hotplug Enterprise SSD + UBM, ///< UBM Backplane + OCP, ///< OCP NIC 3.0 +}; + +enum pcie_link_speed { + MaxSupported, + Gen1, + Gen2, + Gen3, + Gen4, + Gen5, +}; + +/* Sync with PCIE_ASPM_TYPE */ +enum pcie_aspm { + aspm_disabled, + L0s, + L1, + L0sL1, +}; + +struct drivers_amd_opensil_mpio_config { + enum mpio_type type; + uint8_t start_lane; + uint8_t end_lane; + uint8_t gpio_group; + enum mpio_hotplug hotplug; + enum pcie_link_speed speed; + enum pcie_aspm aspm; + uint8_t aspm_l1_1 : 1; + uint8_t aspm_l1_2 : 1; + uint8_t clock_pm : 1; + uint8_t bmc : 1; +}; + +#endif /* OPENSIL_PHOENIX_POC_MPIO_CHIP_H */ diff --git a/src/vendorcode/amd/opensil/phoenix_poc/opensil b/src/vendorcode/amd/opensil/phoenix_poc/opensil new file mode 160000 index 0000000000..52b83c56a3 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/opensil @@ -0,0 +1 @@ +Subproject commit 52b83c56a3a653c287f5839a5986eda22677f304 diff --git a/src/vendorcode/amd/opensil/phoenix_poc/opensil_config.template b/src/vendorcode/amd/opensil/phoenix_poc/opensil_config.template new file mode 100644 index 0000000000..2ddd3b4ec1 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/opensil_config.template @@ -0,0 +1,5 @@ +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 diff --git a/src/vendorcode/amd/opensil/phoenix_poc/opensil_console.c b/src/vendorcode/amd/opensil/phoenix_poc/opensil_console.c new file mode 100644 index 0000000000..35e5eeb2b4 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/opensil_console.c @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include "opensil_console.h" +#include + +static int translate_opensil_debug_level(size_t MsgLevel) +{ + switch (MsgLevel) { + case SIL_TRACE_ERROR: + 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; + default: + return BIOS_NEVER; + } +} + +void HostDebugService(size_t MsgLevel, const char *SilPrefix, const char *Message, + const char *Function, size_t Line, ...) +{ + if (!CONFIG(OPENSIL_DEBUG_OUTPUT)) + return; + + 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 message */ + va_list args; + va_start(args, Line); + vprintk(loglevel, Message, args); + va_end(args); +} diff --git a/src/vendorcode/amd/opensil/phoenix_poc/opensil_console.h b/src/vendorcode/amd/opensil/phoenix_poc/opensil_console.h new file mode 100644 index 0000000000..d3ffb6857f --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/opensil_console.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _VENDORCODE_AND_OPENSIL_CONSOLE +#define _VENDORCODE_AND_OPENSIL_CONSOLE + +void HostDebugService(size_t MsgLevel, const char *SilPrefix, const char *Message, + const char *Function, size_t Line, ...); + +#endif diff --git a/src/vendorcode/amd/opensil/phoenix_poc/ramstage.c b/src/vendorcode/amd/opensil/phoenix_poc/ramstage.c new file mode 100644 index 0000000000..5a037fecb5 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/ramstage.c @@ -0,0 +1,180 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "opensil_console.h" +#include "../opensil.h" + +void SIL_STATUS_report(const char *function, const int status) +{ + const int log_level = status == SilPass ? BIOS_DEBUG : BIOS_ERR; + const char *error_string = "Unknown error"; + + const struct error_string_entry { + SIL_STATUS status; + const char *string; + } errors[] = { + {SilPass, "SilPass"}, + {SilUnsupportedHardware, "SilUnsupportedHardware"}, + {SilUnsupported, "SilUnsupported"}, + {SilInvalidParameter, "SilInvalidParameter"}, + {SilAborted, "SilAborted"}, + {SilOutOfResources, "SilOutOfResources"}, + {SilNotFound, "SilNotFound"}, + {SilOutOfBounds, "SilOutOfBounds"}, + {SilDeviceError, "SilDeviceError"}, + {SilResetRequestColdImm, "SilResetRequestColdImm"}, + {SilResetRequestColdDef, "SilResetRequestColdDef"}, + {SilResetRequestWarmImm, "SilResetRequestWarmImm"}, + {SilResetRequestWarmDef, "SilResetRequestWarmDef"}, + }; + + int i; + for (i = 0; i < ARRAY_SIZE(errors); i++) { + if (errors[i].status == status) + error_string = errors[i].string; + } + 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); + /* 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->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()); + rc_mgr_input_block->Above4GMmioSizePerRbForNonPciDevice = 0; +} + +#define NUM_XHCI_CONTROLLERS 2 +static void configure_usb(void) +{ + const struct soc_amd_phoenix_poc_config *soc_config = config_of_soc(); + 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 */ + for (int i = 0; i < NUM_XHCI_CONTROLLERS; i++) { + memcpy(&fch_usb_data->XhciOCpinSelect[i].Usb20OcPin, &usb->usb2_oc_pins[i], + sizeof(fch_usb_data->XhciOCpinSelect[i].Usb20OcPin)); + memcpy(&fch_usb_data->XhciOCpinSelect[i].Usb31OcPin, &usb->usb3_oc_pins[i], + sizeof(fch_usb_data->XhciOCpinSelect[i].Usb31OcPin)); + } + 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)); +} + +#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(); + for (int i = 0; i < NUM_SATA_CONTROLLERS; i++) { + fch_sata_data[i] = fch_sata_defaults[i]; + fch_sata_data[i].SataSetMaxGen2 = false; + fch_sata_data[i].SataMsiEnable = true; + fch_sata_data[i].SataEspPort = 0xFF; + fch_sata_data[i].SataRasSupport = true; + fch_sata_data[i].SataDevSlpPort1Num = 1; + fch_sata_data[i].SataMsiEnable = true; + fch_sata_data[i].SataControllerAutoShutdown = true; + fch_sata_data[i].SataRxPolarity = 0xFF; + } +} + +void setup_opensil(void) +{ + const SIL_STATUS debug_ret = SilDebugSetup(HostDebugService); + SIL_STATUS_report("SilDebugSetup", debug_ret); + const size_t mem_req = xSimQueryMemoryRequirements(); + void *buf = cbmem_add(CBMEM_ID_AMD_OPENSIL, mem_req); + assert(buf); + /* We run all openSIL timepoints in the same stage so using TP1 as argument is fine. */ + const SIL_STATUS assign_mem_ret = xSimAssignMemoryTp1(buf, mem_req); + SIL_STATUS_report("xSimAssignMemory", assign_mem_ret); + + setup_rc_manager_default(); + configure_usb(); + configure_sata(); +} + +static void opensil_entry(SIL_TIMEPOINT timepoint) +{ + SIL_STATUS ret; + SIL_TIMEPOINT tp = (uintptr_t)timepoint; + + switch (tp) { + case SIL_TP1: + ret = InitializeSiTp1(); + break; + case SIL_TP2: + ret = InitializeSiTp2(); + break; + case SIL_TP3: + ret = InitializeSiTp3(); + break; + default: + printk(BIOS_ERR, "Unknown openSIL timepoint\n"); + return; + } + char opensil_function[16]; + snprintf(opensil_function, sizeof(opensil_function), "InitializeSiTp%d", tp + 1); + SIL_STATUS_report(opensil_function, ret); + if (ret == SilResetRequestColdImm || ret == SilResetRequestColdDef) { + printk(BIOS_INFO, "openSIL requested a cold reset"); + do_cold_reset(); + } else if (ret == SilResetRequestWarmImm || ret == SilResetRequestWarmDef) { + printk(BIOS_INFO, "openSIL requested a warm reset"); + do_warm_reset(); + } +} + +void opensil_xSIM_timepoint_1(void) +{ + opensil_entry(SIL_TP1); +} + +void opensil_xSIM_timepoint_2(void) +{ + opensil_entry(SIL_TP2); +} + +void opensil_xSIM_timepoint_3(void) +{ + opensil_entry(SIL_TP3); +} + +/* TODO: also call timepoints 2 and 3 from coreboot. Are they NOOP? */ diff --git a/src/vendorcode/amd/opensil/phoenix_poc/romstage.c b/src/vendorcode/amd/opensil/phoenix_poc/romstage.c new file mode 100644 index 0000000000..5b871f6025 --- /dev/null +++ b/src/vendorcode/amd/opensil/phoenix_poc/romstage.c @@ -0,0 +1,17 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include +#include "opensil_console.h" +#include +#include + +#include "../opensil.h" + +uintptr_t opensil_get_low_usable_dram_address(void) +{ + SilDebugSetup(HostDebugService); + uintptr_t low_usable_dram_addr = xPrfGetLowUsableDramAddress(0); + printk(BIOS_DEBUG, "xPrfGetLowUsableDramAddress: 0x%lx\n", low_usable_dram_addr); + + return low_usable_dram_addr; +}