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 = { |
Nicholas Sudsgaard | bfb11be | 2024-01-30 09:53:46 +0900 | [diff] [blame] | 13 | .name = "AMD GENOA MPIO", |
Felix Held | e5197e1 | 2024-01-22 18:17:57 +0100 | [diff] [blame] | 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 | |
Felix Held | e261aa0 | 2024-03-18 21:19:45 +0100 | [diff] [blame] | 128 | static void per_device_config(MPIOCLASS_INPUT_BLK *mpio_data, struct device *dev) |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 129 | { |
| 130 | static uint32_t slot_num; |
Arthur Heymans | 7fcd4d5 | 2023-08-24 15:12:19 +0200 | [diff] [blame] | 131 | const uint32_t domain = dev->upstream->dev->path.domain.domain; |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 132 | const uint32_t devfn = dev->path.pci.devfn; |
Felix Held | e261aa0 | 2024-03-18 21:19:45 +0100 | [diff] [blame] | 133 | const struct vendorcode_amd_opensil_genoa_poc_mpio_config *const config = dev->chip_info; |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 134 | printk(BIOS_DEBUG, "Setting MPIO port for domain 0x%x, PCI %d:%d\n", |
| 135 | domain, PCI_SLOT(devfn), PCI_FUNC(devfn)); |
| 136 | |
Felix Held | 929ef5f | 2024-03-15 19:19:46 +0100 | [diff] [blame] | 137 | if (config->type == IFTYPE_UNUSED) { |
| 138 | if (is_dev_enabled(dev)) { |
Felix Held | d7738f7 | 2024-03-21 22:19:30 +0100 | [diff] [blame] | 139 | printk(BIOS_WARNING, "Unused MPIO chip, disabling PCI device.\n"); |
Felix Held | 929ef5f | 2024-03-15 19:19:46 +0100 | [diff] [blame] | 140 | dev->enabled = false; |
Felix Held | 87fa1d0 | 2024-03-21 22:24:26 +0100 | [diff] [blame^] | 141 | } else { |
| 142 | printk(BIOS_DEBUG, "Unused MPIO chip, skipping.\n"); |
Felix Held | 929ef5f | 2024-03-15 19:19:46 +0100 | [diff] [blame] | 143 | } |
| 144 | return; |
| 145 | } |
| 146 | |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 147 | if (config->bmc) { |
| 148 | setup_bmc_lanes(config->start_lane, 0); // TODO support multiple sockets |
| 149 | return; |
| 150 | } |
| 151 | |
| 152 | static int mpio_port = 0; |
| 153 | MPIO_PORT_DESCRIPTOR port = { .Flags = DESCRIPTOR_TERMINATE_LIST }; |
Felix Held | c12ef5d | 2024-03-11 22:31:43 +0100 | [diff] [blame] | 154 | if (config->type == IFTYPE_PCIE) { |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 155 | const MPIO_ENGINE_DATA engine_data = |
| 156 | MPIO_ENGINE_DATA_INITIALIZER(MpioPcieEngine, |
| 157 | config->start_lane, config->end_lane, |
| 158 | config->hotplug == HotplugDisabled ? 0 : 1, |
| 159 | config->gpio_group); |
| 160 | port.EngineData = engine_data; |
| 161 | const MPIO_PORT_DATA port_data = |
Felix Held | b526da2 | 2024-03-11 22:31:54 +0100 | [diff] [blame] | 162 | MPIO_PORT_DATA_INITIALIZER_PCIE(is_dev_enabled(dev) ? |
| 163 | MpioPortEnabled : MpioPortDisabled, |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 164 | PCI_SLOT(devfn), |
| 165 | PCI_FUNC(devfn), |
| 166 | config->hotplug, |
| 167 | config->speed, |
| 168 | 0, // No backup PCIe speed |
| 169 | config->aspm, |
| 170 | config->aspm_l1_1, |
| 171 | config->aspm_l1_2, |
| 172 | config->clock_pm); |
| 173 | port.Port = port_data; |
Felix Held | c12ef5d | 2024-03-11 22:31:43 +0100 | [diff] [blame] | 174 | } else if (config->type == IFTYPE_SATA) { |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 175 | const MPIO_ENGINE_DATA engine_data = |
| 176 | MPIO_ENGINE_DATA_INITIALIZER(MpioSATAEngine, |
| 177 | config->start_lane, config->end_lane, |
| 178 | 0, // meaningless field |
| 179 | config->gpio_group); |
| 180 | port.EngineData = engine_data; |
| 181 | const MPIO_PORT_DATA port_data = { .PortPresent = 1 }; |
| 182 | port.Port = port_data; |
| 183 | |
| 184 | } |
| 185 | port.Port.AlwaysExpose = 1; |
| 186 | port.Port.SlotNum = ++slot_num; |
| 187 | mpio_data->PcieTopologyData.PortList[mpio_port] = port; |
| 188 | /* Update TERMINATE list */ |
| 189 | if (mpio_port > 0) |
| 190 | mpio_data->PcieTopologyData.PortList[mpio_port - 1].Flags = 0; |
| 191 | mpio_port++; |
| 192 | } |
| 193 | |
Felix Held | e5197e1 | 2024-01-22 18:17:57 +0100 | [diff] [blame] | 194 | void configure_mpio(void) |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 195 | { |
| 196 | MPIOCLASS_INPUT_BLK *mpio_data = SilFindStructure(SilId_MpioClass, 0); |
| 197 | mpio_global_config(mpio_data); |
| 198 | nbio_config(); |
| 199 | |
Felix Held | c4e5e91 | 2024-01-22 18:42:35 +0100 | [diff] [blame] | 200 | /* Find all devices with this chip that are directly below the chip */ |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 201 | for (struct device *dev = &dev_root; dev; dev = dev->next) |
Felix Held | c4e5e91 | 2024-01-22 18:42:35 +0100 | [diff] [blame] | 202 | if (dev->chip_ops == &vendorcode_amd_opensil_genoa_poc_mpio_ops && |
Arthur Heymans | 7fcd4d5 | 2023-08-24 15:12:19 +0200 | [diff] [blame] | 203 | dev->chip_info != dev->upstream->dev->chip_info) |
Felix Held | e261aa0 | 2024-03-18 21:19:45 +0100 | [diff] [blame] | 204 | per_device_config(mpio_data, dev); |
Arthur Heymans | f1b1412 | 2023-07-14 20:44:55 +0200 | [diff] [blame] | 205 | } |