blob: 3e16608ca4c8b86f068b559ac717872ff65f0dce [file] [log] [blame]
Jonathan Zhang15fc4592023-01-25 11:33:16 -08001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <assert.h>
4#include <cpu/cpu.h>
5#include <cpu/intel/cpu_ids.h>
6#include <arch/romstage.h>
7#include <console/console.h>
8#include <cbmem.h>
9#include <drivers/vpd/vpd.h>
10#include <drivers/ocp/include/vpd.h>
11#include <security/intel/txt/txt.h>
12#include <fsp/api.h>
13#include <fsp/util.h>
14#include <hob_iiouds.h>
15#include <hob_memmap.h>
16#include <soc/romstage.h>
17#include <soc/pci_devs.h>
Patrick Rudolphc311a712023-09-12 16:24:55 +020018#include <soc/soc_pch.h>
Jonathan Zhang15fc4592023-01-25 11:33:16 -080019#include <soc/intel/common/smbios.h>
20#include <string.h>
21#include <soc/soc_util.h>
22#include <soc/ddr.h>
23
24#include "chip.h"
25
26/* Initialize to all zero first */
Patrick Rudolph76c27c82023-04-11 13:31:39 +020027static UPD_IIO_PCIE_PORT_CONFIG spr_iio_bifur_table[MAX_SOCKET];
28static UINT8 deemphasis_list[MAX_SOCKET * MAX_IIO_PORTS_PER_SOCKET];
Jonathan Zhang15fc4592023-01-25 11:33:16 -080029
30void __weak mainboard_memory_init_params(FSPM_UPD *mupd)
31{
32 /* Default weak implementation */
33}
34
Jonathan Zhang15fc4592023-01-25 11:33:16 -080035/*
36 * Search from VPD_RW first then VPD_RO for UPD config variables,
37 * overwrites them from VPD if it's found.
38 */
39static void config_upd_from_vpd(FSPM_UPD *mupd)
40{
41 uint8_t val;
42 int val_int, cxl_mode;
43
44 /* Send FSP log message to SOL */
45 if (vpd_get_bool(FSP_LOG, VPD_RW_THEN_RO, &val))
46 mupd->FspmConfig.SerialIoUartDebugEnable = val;
47 else {
48 printk(BIOS_INFO,
49 "Not able to get VPD %s, default set "
50 "SerialIoUartDebugEnable to %d\n",
51 FSP_LOG, FSP_LOG_DEFAULT);
52 mupd->FspmConfig.SerialIoUartDebugEnable = FSP_LOG_DEFAULT;
53 }
54
55 if (mupd->FspmConfig.SerialIoUartDebugEnable) {
56 /* FSP memory debug log level */
57 if (vpd_get_int(FSP_MEM_LOG_LEVEL, VPD_RW_THEN_RO, &val_int)) {
58 if (val_int < 0 || val_int > 4) {
59 printk(BIOS_DEBUG,
60 "Invalid serialDebugMsgLvl value from VPD: "
61 "%d\n",
62 val_int);
63 val_int = FSP_MEM_LOG_LEVEL_DEFAULT;
64 }
65 printk(BIOS_DEBUG, "Setting serialDebugMsgLvl to %d\n", val_int);
66 mupd->FspmConfig.serialDebugMsgLvl = (uint8_t)val_int;
67 } else {
68 printk(BIOS_INFO,
69 "Not able to get VPD %s, default set "
70 "DebugPrintLevel to %d\n",
71 FSP_MEM_LOG_LEVEL, FSP_MEM_LOG_LEVEL_DEFAULT);
72 mupd->FspmConfig.serialDebugMsgLvl = FSP_MEM_LOG_LEVEL_DEFAULT;
73 }
74 /* If serialDebugMsgLvl less than 1, disable FSP memory train results */
75 if (mupd->FspmConfig.serialDebugMsgLvl <= 1) {
76 printk(BIOS_DEBUG, "Setting serialDebugMsgLvlTrainResults to 0\n");
77 mupd->FspmConfig.serialDebugMsgLvlTrainResults = 0x0;
78 }
79 }
80
81 /* FSP Dfx PMIC Secure mode */
82 if (vpd_get_int(FSP_PMIC_SECURE_MODE, VPD_RW_THEN_RO, &val_int)) {
83 if (val_int < 0 || val_int > 2) {
84 printk(BIOS_DEBUG,
85 "Invalid PMIC secure mode value from VPD: "
86 "%d\n",
87 val_int);
88 val_int = FSP_PMIC_SECURE_MODE_DEFAULT;
89 }
90 printk(BIOS_DEBUG, "Setting PMIC secure mode to %d\n", val_int);
91 mupd->FspmConfig.DfxPmicSecureMode = (uint8_t)val_int;
92 } else {
93 printk(BIOS_INFO,
94 "Not able to get VPD %s, default set "
95 "PMIC secure mode to %d\n",
96 FSP_PMIC_SECURE_MODE, FSP_PMIC_SECURE_MODE_DEFAULT);
97 mupd->FspmConfig.DfxPmicSecureMode = FSP_PMIC_SECURE_MODE_DEFAULT;
98 }
99
100 cxl_mode = get_cxl_mode_from_vpd();
101 if (cxl_mode == CXL_SYSTEM_MEMORY || cxl_mode == CXL_SPM)
102 mupd->FspmConfig.DfxCxlType3LegacyEn = 1;
103 else /* Disable CXL */
104 mupd->FspmConfig.DfxCxlType3LegacyEn = 0;
105
106 if (CONFIG(INTEL_TXT)) {
107 /* Configure for error injection test */
108 mupd->FspmConfig.DFXEnable = skip_intel_txt_lockdown() ? 1 : 0;
109 }
110}
111
112/* Initialize non-zero default UPD values for IIO */
113static void initialize_iio_upd(FSPM_UPD *mupd)
114{
115 unsigned int port, socket;
116
Arthur Heymansfc95c942021-09-13 09:16:44 +0200117 mupd->FspmConfig.IioPcieConfigTablePtr = (uintptr_t)spr_iio_bifur_table;
Johnny Lin6285a602023-06-30 15:47:42 +0800118 /* MAX_SOCKET is the maximal number defined by FSP, currently is 4. */
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200119 mupd->FspmConfig.IioPcieConfigTableNumber = MAX_SOCKET;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800120 UPD_IIO_PCIE_PORT_CONFIG *PciePortConfig =
121 (UPD_IIO_PCIE_PORT_CONFIG *)spr_iio_bifur_table;
122
123 /* Initialize non-zero default UPD values */
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200124 for (socket = 0; socket < MAX_SOCKET; socket++) {
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800125 for (port = 0; port < MAX_IIO_PORTS_PER_SOCKET; port++) {
126 PciePortConfig[socket].PcieMaxPayload[port] = 0x7; /* Auto */
127 PciePortConfig[socket].DfxDnTxPresetGen3[port] = 0xff; /* Auto */
128 }
129 PciePortConfig[socket].PcieGlobalAspm = 0x1; /* Enable ASPM */
130 PciePortConfig[socket].PcieMaxReadRequestSize = 0x5;
131 }
132
Arthur Heymansfc95c942021-09-13 09:16:44 +0200133 mupd->FspmConfig.DeEmphasisPtr = (uintptr_t)deemphasis_list;
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200134 mupd->FspmConfig.DeEmphasisNumber = MAX_SOCKET * MAX_IIO_PORTS_PER_SOCKET;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800135 UINT8 *DeEmphasisConfig = (UINT8 *)deemphasis_list;
136
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200137 for (port = 0; port < MAX_SOCKET * MAX_IIO_PORTS_PER_SOCKET; port++)
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800138 DeEmphasisConfig[port] = 0x1;
139}
140
Johnny Lin6285a602023-06-30 15:47:42 +0800141void soc_config_iio(FSPM_UPD *mupd, const UPD_IIO_PCIE_PORT_CONFIG_ENTRY
142 mb_iio_table[CONFIG_MAX_SOCKET][IIO_PORT_SETTINGS], const UINT8 mb_iio_bifur[CONFIG_MAX_SOCKET][5])
143{
144 UPD_IIO_PCIE_PORT_CONFIG *PciePortConfig;
145 int port, socket;
146
147 PciePortConfig =
148 (UPD_IIO_PCIE_PORT_CONFIG *)(UINTN)mupd->FspmConfig.IioPcieConfigTablePtr;
149 mupd->FspmConfig.IioPcieConfigTableNumber = CONFIG_MAX_SOCKET; /* Set by mainboard */
150
151 for (socket = 0; socket < CONFIG_MAX_SOCKET; socket++) {
Johnny Lin6285a602023-06-30 15:47:42 +0800152 /* Configures DMI, IOU0 ~ IOU4 */
153 for (port = 0; port < IIO_PORT_SETTINGS; port++) {
154 const UPD_IIO_PCIE_PORT_CONFIG_ENTRY *port_cfg =
155 &mb_iio_table[socket][port];
156 PciePortConfig[socket].SLOTIMP[port] = port_cfg->SLOTIMP;
157 PciePortConfig[socket].SLOTPSP[port] = port_cfg->SLOTPSP;
158 PciePortConfig[socket].SLOTHPCAP[port] = port_cfg->SLOTHPCAP;
159 PciePortConfig[socket].SLOTHPSUP[port] = port_cfg->SLOTHPSUP;
160 PciePortConfig[socket].SLOTSPLS[port] = port_cfg->SLOTSPLS;
161 PciePortConfig[socket].SLOTSPLV[port] = port_cfg->SLOTSPLV;
162 PciePortConfig[socket].VppAddress[port] = port_cfg->VppAddress;
163 PciePortConfig[socket].SLOTPIP[port] = port_cfg->SLOTPIP;
164 PciePortConfig[socket].SLOTAIP[port] = port_cfg->SLOTAIP;
165 PciePortConfig[socket].SLOTMRLSP[port] = port_cfg->SLOTMRLSP;
166 PciePortConfig[socket].SLOTPCP[port] = port_cfg->SLOTPCP;
167 PciePortConfig[socket].SLOTABP[port] = port_cfg->SLOTABP;
168 PciePortConfig[socket].VppEnabled[port] = port_cfg->VppEnabled;
169 PciePortConfig[socket].VppPort[port] = port_cfg->VppPort;
170 PciePortConfig[socket].MuxAddress[port] = port_cfg->MuxAddress;
171 PciePortConfig[socket].PciePortEnable[port] = port_cfg->PciePortEnable;
172 PciePortConfig[socket].PEXPHIDE[port] = port_cfg->PEXPHIDE;
173 PciePortConfig[socket].PcieHotPlugOnPort[port] = port_cfg->PcieHotPlugOnPort;
174 PciePortConfig[socket].PcieMaxPayload[port] = port_cfg->PcieMaxPayload;
175 PciePortConfig[socket].PciePortLinkSpeed[port] = port_cfg->PciePortLinkSpeed;
176 PciePortConfig[socket].DfxDnTxPresetGen3[port] = port_cfg->DfxDnTxPresetGen3;
177 PciePortConfig[socket].HidePEXPMenu[port] = port_cfg->HidePEXPMenu;
178 }
179
180 /* Socket IOU5 ~ IOU6 are not used, set PEXPHIDE and HidePEXPMenu to 1 */
181 for (port = IIO_PORT_SETTINGS; port < MAX_IIO_PORTS_PER_SOCKET;
182 port++) {
183 PciePortConfig[socket].PEXPHIDE[port] = 1;
184 PciePortConfig[socket].HidePEXPMenu[port] = 1;
185 }
186 /* Configure IOU0 ~ IOU4 bifurcation */
187 for (port = 0; port < 5; port++)
188 PciePortConfig[socket].ConfigIOU[port] = mb_iio_bifur[socket][port];
189 }
190}
191
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800192void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
193{
194 FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
195 const config_t *config = config_of_soc();
196
197 m_cfg->DebugPrintLevel = 0xF;
198
199 m_cfg->DirectoryModeEn = 0x2;
200 const u8 KtiFpgaEnable[] = {0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1};
201 memcpy(m_cfg->KtiFpgaEnable, KtiFpgaEnable, sizeof(m_cfg->KtiFpgaEnable));
202
203 m_cfg->TscSyncEn = 0x1;
204
205 m_cfg->mmiohBase = 0x2000;
206 m_cfg->mmiohSize = 0x3;
207
Patrick Rudolph49fe84e2024-03-13 16:43:09 +0100208 /*
209 * By default FSP will set MMCFG size to 256 buses on 1S and 2S platforms
210 * and 512 buses on 4S platforms. 512 buses are implemented by using multiple
211 * PCI segment groups and is likely incompatible with legacy software stacks.
212 */
213 switch (CONFIG_ECAM_MMCONF_BUS_NUMBER) {
214 case 2048:
215 m_cfg->mmCfgSize = 5;
216 break;
217 case 1024:
218 m_cfg->mmCfgSize = 4;
219 break;
220 case 512:
221 m_cfg->mmCfgSize = 3;
222 break;
223 case 256:
224 m_cfg->mmCfgSize = 2;
225 break;
226 case 128:
227 m_cfg->mmCfgSize = 1;
228 break;
229 case 64:
230 m_cfg->mmCfgSize = 0;
231 break;
232 default:
233 printk(BIOS_ERR, "%s: Unsupported ECAM_MMCONF_BUS_NUMBER = %d\n",
234 __func__, CONFIG_ECAM_MMCONF_BUS_NUMBER);
235 }
236
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800237 m_cfg->BoardTypeBitmask = 0x11111133;
238
Patrick Rudolphccbe9a52023-04-04 12:52:16 +0200239 /*
240 * Let coreboot configure LAPIC based on Kconfig.
241 * coreboot currently can only switch from XAPIC to X2APIC,
242 * so always select XAPIC mode here.
243 */
244 m_cfg->X2apic = 0;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800245
246 m_cfg->serialDebugMsgLvl = 0x3;
247
248 m_cfg->VtdSupport = config->vtd_support;
249
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800250 m_cfg->SerialIoUartDebugIoBase = CONFIG_TTYS0_BASE;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800251
252 mupd->FspmConfig.AttemptFastBoot = 1;
253 mupd->FspmConfig.AttemptFastBootCold = 1;
254
255 /* Set Patrol Scrub UPD */
256 mupd->FspmConfig.PatrolScrubNotify = 0x1; /* 1:Enable at ReadyToBootFsp() */
257 mupd->FspmConfig.PatrolScrub = 0x2; /* 2:Enable during
258 NotifyPhase(EnumInitPhaseReadyToBoot) */
259 mupd->FspmConfig.ErrorCheckScrub = 1; /* Enable/Disable DDR5 Error Check
260 and Scrub (ECS) in FSP */
261 mupd->FspmConfig.PatrolScrubAddrMode = 1; /* 1:System Physical Address */
262 mupd->FspmConfig.PatrolScrubDuration = 24; /* unit is hour */
263
264 /* Disable below UPDs because those features should be implemented by coreboot */
265 mupd->FspmConfig.LockChipset = 0;
266 mupd->FspmConfig.ProcessorMsrLockControl = 0;
267 /* Don't set and signal MSR_BIOS_DONE in FSP since it should be done by coreboot */
268 mupd->FspmConfig.DfxDisableBiosDone = 1;
269
270 u32 cpu_id = cpu_get_cpuid();
271 if (cpu_id == (u32)CPUID_SAPPHIRERAPIDS_SP_D) {
272 printk(BIOS_DEBUG, "CPU is D stepping, setting package C state to C0/C1\n");
273 mupd->FspmConfig.CpuPmPackageCState = 0;
274 }
275 /* Set some common UPDs from VPD, mainboard can still override them if needed */
276 if (CONFIG(VPD))
277 config_upd_from_vpd(mupd);
278 initialize_iio_upd(mupd);
279 mainboard_memory_init_params(mupd);
Naresh Solankic7338082023-05-24 10:29:45 +0200280
281 if (CONFIG(ENABLE_IO_MARGINING)) {
282 printk(BIOS_INFO, "IO Margining Enabled.\n");
283 /* Needed for IO Margining */
284 mupd->FspmConfig.DFXEnable = 1;
285
286 UPD_IIO_PCIE_PORT_CONFIG *iio_pcie_cfg;
287 int socket;
288
Arthur Heymansfc95c942021-09-13 09:16:44 +0200289 iio_pcie_cfg = (UPD_IIO_PCIE_PORT_CONFIG *)(uintptr_t)mupd->FspmConfig.IioPcieConfigTablePtr;
Naresh Solankic7338082023-05-24 10:29:45 +0200290
291 for (socket = 0; socket < MAX_SOCKET; socket++)
292 iio_pcie_cfg[socket].PcieGlobalAspm = 0;
293
294 mupd->FspmConfig.KtiLinkL1En = 0;
295 mupd->FspmConfig.KtiLinkL0pEn = 0;
296 }
Naresh Solanki82390fa2023-05-24 11:24:28 +0200297
298 if (CONFIG(ENABLE_RMT)) {
299 printk(BIOS_INFO, "RMT Enabled.\n");
300 mupd->FspmConfig.EnableRMT = 0x1;
301 /* Set FSP debug message to Max for RMT logs */
302 mupd->FspmConfig.serialDebugMsgLvl = 0x3;
Naresh Solanki0a12d2b2023-07-17 15:52:55 +0200303 mupd->FspmConfig.AllowedSocketsInParallel = 0x1;
304 mupd->FspmConfig.EnforcePopulationPor = 0x1;
Naresh Solanki93ffdee52023-10-06 14:35:58 +0200305 if (CONFIG(RMT_MEM_POR_FREQ))
306 mupd->FspmConfig.EnforceDdrMemoryFreqPor = 0x0;
Naresh Solanki82390fa2023-05-24 11:24:28 +0200307 }
Patrick Rudolphc311a712023-09-12 16:24:55 +0200308
309 /* SPR-FSP has no UPD to disable HDA, so do it manually here... */
310 if (!is_devfn_enabled(PCH_DEVFN_HDA))
311 pch_disable_hda();
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800312}
313
314static uint8_t get_error_correction_type(const uint8_t RasModesEnabled)
315{
316 switch (RasModesEnabled) {
317 case CH_INDEPENDENT:
318 return MEMORY_ARRAY_ECC_SINGLE_BIT;
319 case FULL_MIRROR_1LM:
320 case PARTIAL_MIRROR_1LM:
321 case FULL_MIRROR_2LM:
322 case PARTIAL_MIRROR_2LM:
323 return MEMORY_ARRAY_ECC_MULTI_BIT;
324 case RK_SPARE:
325 return MEMORY_ARRAY_ECC_SINGLE_BIT;
326 case CH_LOCKSTEP:
327 return MEMORY_ARRAY_ECC_SINGLE_BIT;
328 default:
329 return MEMORY_ARRAY_ECC_MULTI_BIT;
330 }
331}
332
333/* Save the DIMM information for SMBIOS table 17 */
334void save_dimm_info(void)
335{
336 struct dimm_info *dest_dimm;
337 struct memory_info *mem_info;
338 const struct SystemMemoryMapHob *hob;
339 MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm;
340 int dimm_max, dimm_num = 0;
341 int index = 0;
342 uint8_t mem_dev_type;
343 uint16_t data_width;
344 uint32_t vdd_voltage;
345
346 hob = get_system_memory_map();
347 assert(hob != NULL);
348
349 /*
350 * Allocate CBMEM area for DIMM information used to populate SMBIOS
351 * table 17
352 */
353 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
354 if (mem_info == NULL) {
355 printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
356 return;
357 }
358 memset(mem_info, 0, sizeof(*mem_info));
359 /* According to EDS doc#611488, it's 4 TB per processor. */
360 mem_info->max_capacity_mib = 4 * MiB * CONFIG_MAX_SOCKET;
361 mem_info->number_of_devices = CONFIG_DIMM_MAX;
362 mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled);
363 dimm_max = ARRAY_SIZE(mem_info->dimm);
364 vdd_voltage = get_ddr_millivolt(hob->DdrVoltage);
365 for (int soc = 0; soc < CONFIG_MAX_SOCKET; soc++) {
366 for (int ch = 0; ch < MAX_CH; ch++) {
367 for (int dimm = 0; dimm < MAX_DIMM; dimm++) {
368 if (index >= dimm_max) {
369 printk(BIOS_WARNING, "Too many DIMMs info for %s.\n",
370 __func__);
371 return;
372 }
373
374 src_dimm = hob->Socket[soc].ChannelInfo[ch].DimmInfo[dimm];
375 if (src_dimm.Present) {
376 dest_dimm = &mem_info->dimm[index];
377 index++;
378 } else if (mainboard_dimm_slot_exists(soc, ch, dimm)) {
379 dest_dimm = &mem_info->dimm[index];
380 index++;
381 /* Save DIMM Locator information for SMBIOS Type 17 */
382 dest_dimm->dimm_size = 0;
383 dest_dimm->soc_num = soc;
384 dest_dimm->channel_num = ch;
385 dest_dimm->dimm_num = dimm;
386 continue;
387 } else {
388 /* Ignore DIMM that isn't present and doesn't exist on
389 the board. */
390 continue;
391 }
Eric Laib15946d2023-06-13 10:21:58 +0800392
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800393 dest_dimm->soc_num = soc;
394
395 if (hob->DramType == SPD_TYPE_DDR5) {
396 /* hard-coded memory device type as DDR5 */
397 mem_dev_type = 0x22;
398 data_width = 64;
399 } else {
400 /* hard-coded memory device type as DDR4 */
401 mem_dev_type = 0x1A;
402 data_width = 64;
403 }
404 dimm_info_fill(
405 dest_dimm, src_dimm.DimmSize << 6, mem_dev_type,
406 hob->memFreq, /* replaced by configured_speed_mts */
407 src_dimm.NumRanks,
408 ch, /* for mainboard locator string override */
409 dimm, /* for mainboard locator string override */
410 (const char *)&src_dimm.PartNumber[0],
411 sizeof(src_dimm.PartNumber),
412 (const uint8_t *)&src_dimm.serialNumber[0], data_width,
413 vdd_voltage, true, /* hard-coded as ECC supported */
Eric Laib15946d2023-06-13 10:21:58 +0800414 src_dimm.VendorID, src_dimm.actKeyByte2, 0,
415 get_max_memory_speed(src_dimm.commonTck));
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800416 dimm_num++;
417 }
418 }
419 }
420
421 mem_info->dimm_cnt = index; /* Number of DIMM slots found */
422 printk(BIOS_DEBUG, "%d Installed DIMMs found\n", dimm_num);
423}