Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <RcMgr/DfX/RcManager4-api.h> |
| 4 | #include <NBIO/NbioClass-api.h> |
| 5 | #include <Mpio/MpioClass-api.h> |
| 6 | #include <Mpio/Common/MpioStructs.h> |
| 7 | #include <device/device.h> |
| 8 | #include <device/pci_def.h> |
| 9 | #include "chip.h" |
Felix Held | e5197e1 | 2024-01-22 18:17:57 +0100 | [diff] [blame] | 10 | #include "../opensil.h" |
| 11 | |
| 12 | struct chip_operations vendorcode_amd_opensil_genoa_poc_mpio_ops = { |
| 13 | CHIP_NAME("AMD GENOA MPIO") |
| 14 | }; |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 15 | |
| 16 | static void nbio_config(void) |
| 17 | { |
| 18 | NBIOCLASS_DATA_BLOCK *nbio_data = SilFindStructure(SilId_NbioClass, 0); |
| 19 | NBIOCLASS_INPUT_BLK *input = &nbio_data->NbioInputBlk; |
| 20 | input->CfgHdAudioEnable = false; |
| 21 | input->EsmEnableAllRootPorts = false; |
| 22 | input->EsmTargetSpeed = 16; |
| 23 | input->CfgRxMarginPersistenceMode = 1; |
| 24 | input->CfgDxioFrequencyVetting = false; |
| 25 | input->CfgSkipPspMessage = 1; |
| 26 | input->CfgEarlyTrainTwoPcieLinks = false; |
| 27 | input->EarlyBmcLinkTraining = true; |
| 28 | input->EdpcEnable = 0; |
| 29 | input->PcieAerReportMechanism = 2; |
| 30 | input->SevSnpSupport = false; |
| 31 | } |
| 32 | |
| 33 | static void mpio_global_config(MPIOCLASS_INPUT_BLK *mpio_data) |
| 34 | { |
| 35 | mpio_data->CfgDxioClockGating = 1; |
| 36 | mpio_data->PcieDxioTimingControlEnable = 0; |
| 37 | mpio_data->PCIELinkReceiverDetectionPolling = 0; |
| 38 | mpio_data->PCIELinkResetToTrainingTime = 0; |
| 39 | mpio_data->PCIELinkL0Polling = 0; |
| 40 | mpio_data->PCIeExactMatchEnable = 0; |
| 41 | mpio_data->DxioPhyValid = 1; |
| 42 | mpio_data->DxioPhyProgramming = 1; |
| 43 | mpio_data->CfgSkipPspMessage = 1; |
| 44 | mpio_data->DxioSaveRestoreModes = 0xff; |
| 45 | mpio_data->AmdAllowCompliance = 0; |
| 46 | mpio_data->AmdAllowCompliance = 0xff; |
| 47 | mpio_data->SrisEnableMode = 0xff; |
| 48 | mpio_data->SrisSkipInterval = 0; |
| 49 | mpio_data->SrisSkpIntervalSel = 1; |
| 50 | mpio_data->SrisCfgType = 0; |
| 51 | mpio_data->SrisAutoDetectMode = 0xff; |
| 52 | mpio_data->SrisAutodetectFactor = 0; |
| 53 | mpio_data->SrisLowerSkpOsGenSup = 0; |
| 54 | mpio_data->SrisLowerSkpOsRcvSup = 0; |
| 55 | mpio_data->AmdCxlOnAllPorts = 1; |
| 56 | mpio_data->CxlCorrectableErrorLogging = 1; |
| 57 | mpio_data->CxlUnCorrectableErrorLogging = 1; |
| 58 | // This is also available in Nbio. How to handle duplicate entries? |
| 59 | mpio_data->CfgAEREnable = 1; |
| 60 | mpio_data->CfgMcCapEnable = 0; |
| 61 | mpio_data->CfgRcvErrEnable = 0; |
| 62 | mpio_data->EarlyBmcLinkTraining = 1; |
| 63 | mpio_data->SurpriseDownFeature = 1; |
| 64 | mpio_data->LcMultAutoSpdChgOnLastRateEnable = 0; |
| 65 | mpio_data->AmdRxMarginEnabled = 1; |
| 66 | mpio_data->CfgPcieCVTestWA = 1; |
| 67 | mpio_data->CfgPcieAriSupport = 1; |
| 68 | mpio_data->CfgNbioCTOtoSC = 0; |
| 69 | mpio_data->CfgNbioCTOIgnoreError = 1; |
| 70 | mpio_data->CfgNbioSsid = 0; |
| 71 | mpio_data->CfgIommuSsid = 0; |
| 72 | mpio_data->CfgPspccpSsid = 0; |
| 73 | mpio_data->CfgNtbccpSsid = 0; |
| 74 | mpio_data->CfgNbifF0Ssid = 0; |
| 75 | mpio_data->CfgNtbSsid = 0; |
| 76 | mpio_data->AmdPcieSubsystemDeviceID = 0x1453; |
| 77 | mpio_data->AmdPcieSubsystemVendorID = 0x1022; |
| 78 | mpio_data->GppAtomicOps = 1; |
| 79 | mpio_data->GfxAtomicOps = 1; |
| 80 | mpio_data->AmdNbioReportEdbErrors = 0; |
| 81 | mpio_data->OpnSpare = 0; |
| 82 | mpio_data->AmdPreSilCtrl0 = 0; |
| 83 | mpio_data->MPIOAncDataSupport = 1; |
| 84 | mpio_data->AfterResetDelay = 0; |
| 85 | mpio_data->CfgEarlyLink = 0; |
| 86 | mpio_data->AmdCfgExposeUnusedPciePorts = 1; // Show all ports |
| 87 | mpio_data->CfgForcePcieGenSpeed = 0; |
| 88 | mpio_data->CfgSataPhyTuning = 0; |
| 89 | mpio_data->PcieLinkComplianceModeAllPorts = 0; |
| 90 | mpio_data->AmdMCTPEnable = 0; |
| 91 | mpio_data->SbrBrokenLaneAvoidanceSup = 1; |
| 92 | mpio_data->AutoFullMarginSup = 1; |
| 93 | // A getter and setter, both are needed for this PCD. |
| 94 | mpio_data->AmdPciePresetMask8GtAllPort = 0xffffffff; |
| 95 | // A getter and setter, both are needed for this PCD. |
| 96 | mpio_data->AmdPciePresetMask16GtAllPort = 0xffffffff; |
| 97 | // A getter and setter, both are needed for this PCD. |
| 98 | mpio_data->AmdPciePresetMask32GtAllPort = 0xffffffff; |
| 99 | mpio_data->PcieLinkAspmAllPort = 0xff; |
| 100 | |
| 101 | mpio_data->SyncHeaderByPass = 1; |
| 102 | mpio_data->CxlTempGen5AdvertAltPtcl = 0; |
| 103 | |
| 104 | /* TODO handle this differently on multisocket */ |
| 105 | mpio_data->PcieTopologyData.PlatformData[0].Flags = DESCRIPTOR_TERMINATE_LIST; |
| 106 | mpio_data->PcieTopologyData.PlatformData[0].PciePortList = mpio_data->PcieTopologyData.PortList; |
| 107 | |
| 108 | } |
| 109 | |
| 110 | static void setup_bmc_lanes(uint8_t lane, uint8_t socket) |
| 111 | { |
| 112 | DFX_RCMGR_INPUT_BLK *rc_mgr_input_block = SilFindStructure(SilId_RcManager, 0); |
| 113 | rc_mgr_input_block->BmcSocket = socket; |
| 114 | rc_mgr_input_block->EarlyBmcLinkLaneNum = lane; |
| 115 | |
| 116 | NBIOCLASS_DATA_BLOCK *nbio_data = SilFindStructure(SilId_NbioClass, 0); |
| 117 | NBIOCLASS_INPUT_BLK *nbio_input = &nbio_data->NbioInputBlk; |
| 118 | nbio_input->EarlyBmcLinkSocket = socket; |
| 119 | nbio_input->EarlyBmcLinkLaneNum = lane; |
| 120 | nbio_input->EarlyBmcLinkDie = 0; |
| 121 | |
| 122 | MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0); |
| 123 | mpio_data->EarlyBmcLinkSocket = socket; |
| 124 | mpio_data->EarlyBmcLinkLaneNum = lane; |
| 125 | mpio_data->EarlyBmcLinkDie = 0; |
| 126 | } |
| 127 | |
| 128 | static void per_device_config(MPIOCLASS_INPUT_BLK *mpio_data, struct device *dev, |
| 129 | struct vendorcode_amd_opensil_genoa_poc_mpio_config *const config) |
| 130 | { |
| 131 | static uint32_t slot_num; |
| 132 | const uint32_t domain = dev->bus->dev->path.domain.domain; |
| 133 | const uint32_t devfn = dev->path.pci.devfn; |
| 134 | printk(BIOS_DEBUG, "Setting MPIO port for domain 0x%x, PCI %d:%d\n", |
| 135 | domain, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
| 136 | |
| 137 | if (config->bmc) { |
| 138 | setup_bmc_lanes(config->start_lane, 0); // TODO support multiple sockets |
| 139 | return; |
| 140 | } |
| 141 | |
| 142 | static int mpio_port = 0; |
| 143 | MPIO_PORT_DESCRIPTOR port = { .Flags = DESCRIPTOR_TERMINATE_LIST }; |
| 144 | if (config->type == PCIE) { |
| 145 | const MPIO_ENGINE_DATA engine_data = |
| 146 | MPIO_ENGINE_DATA_INITIALIZER(MpioPcieEngine, |
| 147 | config->start_lane, config->end_lane, |
| 148 | config->hotplug == HotplugDisabled ? 0 : 1, |
| 149 | config->gpio_group); |
| 150 | port.EngineData = engine_data; |
| 151 | const MPIO_PORT_DATA port_data = |
| 152 | MPIO_PORT_DATA_INITIALIZER_PCIE(MpioPortEnabled, |
| 153 | PCI_SLOT(devfn), |
| 154 | PCI_FUNC(devfn), |
| 155 | config->hotplug, |
| 156 | config->speed, |
| 157 | 0, // No backup PCIe speed |
| 158 | config->aspm, |
| 159 | config->aspm_l1_1, |
| 160 | config->aspm_l1_2, |
| 161 | config->clock_pm); |
| 162 | port.Port = port_data; |
| 163 | } else if (config->type == SATA) { |
| 164 | const MPIO_ENGINE_DATA engine_data = |
| 165 | MPIO_ENGINE_DATA_INITIALIZER(MpioSATAEngine, |
| 166 | config->start_lane, config->end_lane, |
| 167 | 0, // meaningless field |
| 168 | config->gpio_group); |
| 169 | port.EngineData = engine_data; |
| 170 | const MPIO_PORT_DATA port_data = { .PortPresent = 1 }; |
| 171 | port.Port = port_data; |
| 172 | |
| 173 | } |
| 174 | port.Port.AlwaysExpose = 1; |
| 175 | port.Port.SlotNum = ++slot_num; |
| 176 | mpio_data->PcieTopologyData.PortList[mpio_port] = port; |
| 177 | /* Update TERMINATE list */ |
| 178 | if (mpio_port > 0) |
| 179 | mpio_data->PcieTopologyData.PortList[mpio_port - 1].Flags = 0; |
| 180 | mpio_port++; |
| 181 | } |
| 182 | |
Felix Held | e5197e1 | 2024-01-22 18:17:57 +0100 | [diff] [blame] | 183 | void configure_mpio(void) |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 184 | { |
| 185 | MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0); |
| 186 | mpio_global_config(mpio_data); |
| 187 | nbio_config(); |
| 188 | |
Felix Held | c4e5e91 | 2024-01-22 18:42:35 +0100 | [diff] [blame] | 189 | /* Find all devices with this chip that are directly below the chip */ |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 190 | for (struct device *dev = &dev_root; dev; dev = dev->next) |
Felix Held | c4e5e91 | 2024-01-22 18:42:35 +0100 | [diff] [blame] | 191 | if (dev->chip_ops == &vendorcode_amd_opensil_genoa_poc_mpio_ops && |
| 192 | dev->chip_info != dev->bus->dev->chip_info) |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 193 | per_device_config(mpio_data, dev->bus->dev, dev->chip_info); |
| 194 | } |