| /* SPDX-License-Identifier: GPL-2.0-only */ |
| |
| #include <RcMgr/DfX/RcManager4-api.h> |
| #include <NBIO/NbioClass-api.h> |
| #include <Mpio/MpioClass-api.h> |
| #include <Mpio/Common/MpioStructs.h> |
| #include <device/device.h> |
| #include <device/pci_def.h> |
| #include "chip.h" |
| #include "../opensil.h" |
| |
| struct chip_operations vendorcode_amd_opensil_genoa_poc_mpio_ops = { |
| .name = "AMD GENOA MPIO", |
| }; |
| |
| static void nbio_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 mpio_global_config(MPIOCLASS_INPUT_BLK *mpio_data) |
| { |
| 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 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; |
| } |
| |
| static void per_device_config(MPIOCLASS_INPUT_BLK *mpio_data, struct device *dev, |
| struct vendorcode_amd_opensil_genoa_poc_mpio_config *const config) |
| { |
| static uint32_t slot_num; |
| const uint32_t domain = dev->bus->dev->path.domain.domain; |
| const uint32_t devfn = dev->path.pci.devfn; |
| printk(BIOS_DEBUG, "Setting MPIO port for domain 0x%x, PCI %d:%d\n", |
| domain, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
| |
| 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 == 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(MpioPortEnabled, |
| 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 == 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 configure_mpio(void) |
| { |
| MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0); |
| mpio_global_config(mpio_data); |
| nbio_config(); |
| |
| /* Find all devices with this chip that are directly below the chip */ |
| for (struct device *dev = &dev_root; dev; dev = dev->next) |
| if (dev->chip_ops == &vendorcode_amd_opensil_genoa_poc_mpio_ops && |
| dev->chip_info != dev->bus->dev->chip_info) |
| per_device_config(mpio_data, dev->bus->dev, dev->chip_info); |
| } |