blob: 4cce21f249678c253571dee442274a99dbcf73fa [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
35bool __weak mainboard_dimm_slot_exists(uint8_t socket, uint8_t channel, uint8_t dimm)
36{
37 return false;
38}
39
40/*
41 * Search from VPD_RW first then VPD_RO for UPD config variables,
42 * overwrites them from VPD if it's found.
43 */
44static void config_upd_from_vpd(FSPM_UPD *mupd)
45{
46 uint8_t val;
47 int val_int, cxl_mode;
48
49 /* Send FSP log message to SOL */
50 if (vpd_get_bool(FSP_LOG, VPD_RW_THEN_RO, &val))
51 mupd->FspmConfig.SerialIoUartDebugEnable = val;
52 else {
53 printk(BIOS_INFO,
54 "Not able to get VPD %s, default set "
55 "SerialIoUartDebugEnable to %d\n",
56 FSP_LOG, FSP_LOG_DEFAULT);
57 mupd->FspmConfig.SerialIoUartDebugEnable = FSP_LOG_DEFAULT;
58 }
59
60 if (mupd->FspmConfig.SerialIoUartDebugEnable) {
61 /* FSP memory debug log level */
62 if (vpd_get_int(FSP_MEM_LOG_LEVEL, VPD_RW_THEN_RO, &val_int)) {
63 if (val_int < 0 || val_int > 4) {
64 printk(BIOS_DEBUG,
65 "Invalid serialDebugMsgLvl value from VPD: "
66 "%d\n",
67 val_int);
68 val_int = FSP_MEM_LOG_LEVEL_DEFAULT;
69 }
70 printk(BIOS_DEBUG, "Setting serialDebugMsgLvl to %d\n", val_int);
71 mupd->FspmConfig.serialDebugMsgLvl = (uint8_t)val_int;
72 } else {
73 printk(BIOS_INFO,
74 "Not able to get VPD %s, default set "
75 "DebugPrintLevel to %d\n",
76 FSP_MEM_LOG_LEVEL, FSP_MEM_LOG_LEVEL_DEFAULT);
77 mupd->FspmConfig.serialDebugMsgLvl = FSP_MEM_LOG_LEVEL_DEFAULT;
78 }
79 /* If serialDebugMsgLvl less than 1, disable FSP memory train results */
80 if (mupd->FspmConfig.serialDebugMsgLvl <= 1) {
81 printk(BIOS_DEBUG, "Setting serialDebugMsgLvlTrainResults to 0\n");
82 mupd->FspmConfig.serialDebugMsgLvlTrainResults = 0x0;
83 }
84 }
85
86 /* FSP Dfx PMIC Secure mode */
87 if (vpd_get_int(FSP_PMIC_SECURE_MODE, VPD_RW_THEN_RO, &val_int)) {
88 if (val_int < 0 || val_int > 2) {
89 printk(BIOS_DEBUG,
90 "Invalid PMIC secure mode value from VPD: "
91 "%d\n",
92 val_int);
93 val_int = FSP_PMIC_SECURE_MODE_DEFAULT;
94 }
95 printk(BIOS_DEBUG, "Setting PMIC secure mode to %d\n", val_int);
96 mupd->FspmConfig.DfxPmicSecureMode = (uint8_t)val_int;
97 } else {
98 printk(BIOS_INFO,
99 "Not able to get VPD %s, default set "
100 "PMIC secure mode to %d\n",
101 FSP_PMIC_SECURE_MODE, FSP_PMIC_SECURE_MODE_DEFAULT);
102 mupd->FspmConfig.DfxPmicSecureMode = FSP_PMIC_SECURE_MODE_DEFAULT;
103 }
104
105 cxl_mode = get_cxl_mode_from_vpd();
106 if (cxl_mode == CXL_SYSTEM_MEMORY || cxl_mode == CXL_SPM)
107 mupd->FspmConfig.DfxCxlType3LegacyEn = 1;
108 else /* Disable CXL */
109 mupd->FspmConfig.DfxCxlType3LegacyEn = 0;
110
111 if (CONFIG(INTEL_TXT)) {
112 /* Configure for error injection test */
113 mupd->FspmConfig.DFXEnable = skip_intel_txt_lockdown() ? 1 : 0;
114 }
115}
116
117/* Initialize non-zero default UPD values for IIO */
118static void initialize_iio_upd(FSPM_UPD *mupd)
119{
120 unsigned int port, socket;
121
122 mupd->FspmConfig.IioPcieConfigTablePtr = (UINT32)spr_iio_bifur_table;
Johnny Lin6285a602023-06-30 15:47:42 +0800123 /* MAX_SOCKET is the maximal number defined by FSP, currently is 4. */
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200124 mupd->FspmConfig.IioPcieConfigTableNumber = MAX_SOCKET;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800125 UPD_IIO_PCIE_PORT_CONFIG *PciePortConfig =
126 (UPD_IIO_PCIE_PORT_CONFIG *)spr_iio_bifur_table;
127
128 /* Initialize non-zero default UPD values */
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200129 for (socket = 0; socket < MAX_SOCKET; socket++) {
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800130 for (port = 0; port < MAX_IIO_PORTS_PER_SOCKET; port++) {
131 PciePortConfig[socket].PcieMaxPayload[port] = 0x7; /* Auto */
132 PciePortConfig[socket].DfxDnTxPresetGen3[port] = 0xff; /* Auto */
133 }
134 PciePortConfig[socket].PcieGlobalAspm = 0x1; /* Enable ASPM */
135 PciePortConfig[socket].PcieMaxReadRequestSize = 0x5;
136 }
137
138 mupd->FspmConfig.DeEmphasisPtr = (UINT32)deemphasis_list;
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200139 mupd->FspmConfig.DeEmphasisNumber = MAX_SOCKET * MAX_IIO_PORTS_PER_SOCKET;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800140 UINT8 *DeEmphasisConfig = (UINT8 *)deemphasis_list;
141
Patrick Rudolph76c27c82023-04-11 13:31:39 +0200142 for (port = 0; port < MAX_SOCKET * MAX_IIO_PORTS_PER_SOCKET; port++)
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800143 DeEmphasisConfig[port] = 0x1;
144}
145
Johnny Lin6285a602023-06-30 15:47:42 +0800146void soc_config_iio(FSPM_UPD *mupd, const UPD_IIO_PCIE_PORT_CONFIG_ENTRY
147 mb_iio_table[CONFIG_MAX_SOCKET][IIO_PORT_SETTINGS], const UINT8 mb_iio_bifur[CONFIG_MAX_SOCKET][5])
148{
149 UPD_IIO_PCIE_PORT_CONFIG *PciePortConfig;
150 int port, socket;
151
152 PciePortConfig =
153 (UPD_IIO_PCIE_PORT_CONFIG *)(UINTN)mupd->FspmConfig.IioPcieConfigTablePtr;
154 mupd->FspmConfig.IioPcieConfigTableNumber = CONFIG_MAX_SOCKET; /* Set by mainboard */
155
156 for (socket = 0; socket < CONFIG_MAX_SOCKET; socket++) {
157
158 /* Configures DMI, IOU0 ~ IOU4 */
159 for (port = 0; port < IIO_PORT_SETTINGS; port++) {
160 const UPD_IIO_PCIE_PORT_CONFIG_ENTRY *port_cfg =
161 &mb_iio_table[socket][port];
162 PciePortConfig[socket].SLOTIMP[port] = port_cfg->SLOTIMP;
163 PciePortConfig[socket].SLOTPSP[port] = port_cfg->SLOTPSP;
164 PciePortConfig[socket].SLOTHPCAP[port] = port_cfg->SLOTHPCAP;
165 PciePortConfig[socket].SLOTHPSUP[port] = port_cfg->SLOTHPSUP;
166 PciePortConfig[socket].SLOTSPLS[port] = port_cfg->SLOTSPLS;
167 PciePortConfig[socket].SLOTSPLV[port] = port_cfg->SLOTSPLV;
168 PciePortConfig[socket].VppAddress[port] = port_cfg->VppAddress;
169 PciePortConfig[socket].SLOTPIP[port] = port_cfg->SLOTPIP;
170 PciePortConfig[socket].SLOTAIP[port] = port_cfg->SLOTAIP;
171 PciePortConfig[socket].SLOTMRLSP[port] = port_cfg->SLOTMRLSP;
172 PciePortConfig[socket].SLOTPCP[port] = port_cfg->SLOTPCP;
173 PciePortConfig[socket].SLOTABP[port] = port_cfg->SLOTABP;
174 PciePortConfig[socket].VppEnabled[port] = port_cfg->VppEnabled;
175 PciePortConfig[socket].VppPort[port] = port_cfg->VppPort;
176 PciePortConfig[socket].MuxAddress[port] = port_cfg->MuxAddress;
177 PciePortConfig[socket].PciePortEnable[port] = port_cfg->PciePortEnable;
178 PciePortConfig[socket].PEXPHIDE[port] = port_cfg->PEXPHIDE;
179 PciePortConfig[socket].PcieHotPlugOnPort[port] = port_cfg->PcieHotPlugOnPort;
180 PciePortConfig[socket].PcieMaxPayload[port] = port_cfg->PcieMaxPayload;
181 PciePortConfig[socket].PciePortLinkSpeed[port] = port_cfg->PciePortLinkSpeed;
182 PciePortConfig[socket].DfxDnTxPresetGen3[port] = port_cfg->DfxDnTxPresetGen3;
183 PciePortConfig[socket].HidePEXPMenu[port] = port_cfg->HidePEXPMenu;
184 }
185
186 /* Socket IOU5 ~ IOU6 are not used, set PEXPHIDE and HidePEXPMenu to 1 */
187 for (port = IIO_PORT_SETTINGS; port < MAX_IIO_PORTS_PER_SOCKET;
188 port++) {
189 PciePortConfig[socket].PEXPHIDE[port] = 1;
190 PciePortConfig[socket].HidePEXPMenu[port] = 1;
191 }
192 /* Configure IOU0 ~ IOU4 bifurcation */
193 for (port = 0; port < 5; port++)
194 PciePortConfig[socket].ConfigIOU[port] = mb_iio_bifur[socket][port];
195 }
196}
197
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800198void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
199{
200 FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
201 const config_t *config = config_of_soc();
202
203 m_cfg->DebugPrintLevel = 0xF;
204
205 m_cfg->DirectoryModeEn = 0x2;
206 const u8 KtiFpgaEnable[] = {0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1};
207 memcpy(m_cfg->KtiFpgaEnable, KtiFpgaEnable, sizeof(m_cfg->KtiFpgaEnable));
208
209 m_cfg->TscSyncEn = 0x1;
210
211 m_cfg->mmiohBase = 0x2000;
212 m_cfg->mmiohSize = 0x3;
213
214 m_cfg->BoardTypeBitmask = 0x11111133;
215
Patrick Rudolphccbe9a52023-04-04 12:52:16 +0200216 /*
217 * Let coreboot configure LAPIC based on Kconfig.
218 * coreboot currently can only switch from XAPIC to X2APIC,
219 * so always select XAPIC mode here.
220 */
221 m_cfg->X2apic = 0;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800222
223 m_cfg->serialDebugMsgLvl = 0x3;
224
225 m_cfg->VtdSupport = config->vtd_support;
226
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800227 m_cfg->SerialIoUartDebugIoBase = CONFIG_TTYS0_BASE;
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800228
229 mupd->FspmConfig.AttemptFastBoot = 1;
230 mupd->FspmConfig.AttemptFastBootCold = 1;
231
232 /* Set Patrol Scrub UPD */
233 mupd->FspmConfig.PatrolScrubNotify = 0x1; /* 1:Enable at ReadyToBootFsp() */
234 mupd->FspmConfig.PatrolScrub = 0x2; /* 2:Enable during
235 NotifyPhase(EnumInitPhaseReadyToBoot) */
236 mupd->FspmConfig.ErrorCheckScrub = 1; /* Enable/Disable DDR5 Error Check
237 and Scrub (ECS) in FSP */
238 mupd->FspmConfig.PatrolScrubAddrMode = 1; /* 1:System Physical Address */
239 mupd->FspmConfig.PatrolScrubDuration = 24; /* unit is hour */
240
241 /* Disable below UPDs because those features should be implemented by coreboot */
242 mupd->FspmConfig.LockChipset = 0;
243 mupd->FspmConfig.ProcessorMsrLockControl = 0;
244 /* Don't set and signal MSR_BIOS_DONE in FSP since it should be done by coreboot */
245 mupd->FspmConfig.DfxDisableBiosDone = 1;
246
247 u32 cpu_id = cpu_get_cpuid();
248 if (cpu_id == (u32)CPUID_SAPPHIRERAPIDS_SP_D) {
249 printk(BIOS_DEBUG, "CPU is D stepping, setting package C state to C0/C1\n");
250 mupd->FspmConfig.CpuPmPackageCState = 0;
251 }
252 /* Set some common UPDs from VPD, mainboard can still override them if needed */
253 if (CONFIG(VPD))
254 config_upd_from_vpd(mupd);
255 initialize_iio_upd(mupd);
256 mainboard_memory_init_params(mupd);
Naresh Solankic7338082023-05-24 10:29:45 +0200257
258 if (CONFIG(ENABLE_IO_MARGINING)) {
259 printk(BIOS_INFO, "IO Margining Enabled.\n");
260 /* Needed for IO Margining */
261 mupd->FspmConfig.DFXEnable = 1;
262
263 UPD_IIO_PCIE_PORT_CONFIG *iio_pcie_cfg;
264 int socket;
265
266 iio_pcie_cfg = (UPD_IIO_PCIE_PORT_CONFIG *)mupd->FspmConfig.IioPcieConfigTablePtr;
267
268 for (socket = 0; socket < MAX_SOCKET; socket++)
269 iio_pcie_cfg[socket].PcieGlobalAspm = 0;
270
271 mupd->FspmConfig.KtiLinkL1En = 0;
272 mupd->FspmConfig.KtiLinkL0pEn = 0;
273 }
Naresh Solanki82390fa2023-05-24 11:24:28 +0200274
275 if (CONFIG(ENABLE_RMT)) {
276 printk(BIOS_INFO, "RMT Enabled.\n");
277 mupd->FspmConfig.EnableRMT = 0x1;
278 /* Set FSP debug message to Max for RMT logs */
279 mupd->FspmConfig.serialDebugMsgLvl = 0x3;
Naresh Solanki0a12d2b2023-07-17 15:52:55 +0200280 mupd->FspmConfig.AllowedSocketsInParallel = 0x1;
281 mupd->FspmConfig.EnforcePopulationPor = 0x1;
Naresh Solanki93ffdee52023-10-06 14:35:58 +0200282 if (CONFIG(RMT_MEM_POR_FREQ))
283 mupd->FspmConfig.EnforceDdrMemoryFreqPor = 0x0;
Naresh Solanki82390fa2023-05-24 11:24:28 +0200284 }
Patrick Rudolphc311a712023-09-12 16:24:55 +0200285
286 /* SPR-FSP has no UPD to disable HDA, so do it manually here... */
287 if (!is_devfn_enabled(PCH_DEVFN_HDA))
288 pch_disable_hda();
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800289}
290
291static uint8_t get_error_correction_type(const uint8_t RasModesEnabled)
292{
293 switch (RasModesEnabled) {
294 case CH_INDEPENDENT:
295 return MEMORY_ARRAY_ECC_SINGLE_BIT;
296 case FULL_MIRROR_1LM:
297 case PARTIAL_MIRROR_1LM:
298 case FULL_MIRROR_2LM:
299 case PARTIAL_MIRROR_2LM:
300 return MEMORY_ARRAY_ECC_MULTI_BIT;
301 case RK_SPARE:
302 return MEMORY_ARRAY_ECC_SINGLE_BIT;
303 case CH_LOCKSTEP:
304 return MEMORY_ARRAY_ECC_SINGLE_BIT;
305 default:
306 return MEMORY_ARRAY_ECC_MULTI_BIT;
307 }
308}
309
310/* Save the DIMM information for SMBIOS table 17 */
311void save_dimm_info(void)
312{
313 struct dimm_info *dest_dimm;
314 struct memory_info *mem_info;
315 const struct SystemMemoryMapHob *hob;
316 MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm;
317 int dimm_max, dimm_num = 0;
318 int index = 0;
319 uint8_t mem_dev_type;
320 uint16_t data_width;
321 uint32_t vdd_voltage;
322
323 hob = get_system_memory_map();
324 assert(hob != NULL);
325
326 /*
327 * Allocate CBMEM area for DIMM information used to populate SMBIOS
328 * table 17
329 */
330 mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info));
331 if (mem_info == NULL) {
332 printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n");
333 return;
334 }
335 memset(mem_info, 0, sizeof(*mem_info));
336 /* According to EDS doc#611488, it's 4 TB per processor. */
337 mem_info->max_capacity_mib = 4 * MiB * CONFIG_MAX_SOCKET;
338 mem_info->number_of_devices = CONFIG_DIMM_MAX;
339 mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled);
340 dimm_max = ARRAY_SIZE(mem_info->dimm);
341 vdd_voltage = get_ddr_millivolt(hob->DdrVoltage);
342 for (int soc = 0; soc < CONFIG_MAX_SOCKET; soc++) {
343 for (int ch = 0; ch < MAX_CH; ch++) {
344 for (int dimm = 0; dimm < MAX_DIMM; dimm++) {
345 if (index >= dimm_max) {
346 printk(BIOS_WARNING, "Too many DIMMs info for %s.\n",
347 __func__);
348 return;
349 }
350
351 src_dimm = hob->Socket[soc].ChannelInfo[ch].DimmInfo[dimm];
352 if (src_dimm.Present) {
353 dest_dimm = &mem_info->dimm[index];
354 index++;
355 } else if (mainboard_dimm_slot_exists(soc, ch, dimm)) {
356 dest_dimm = &mem_info->dimm[index];
357 index++;
358 /* Save DIMM Locator information for SMBIOS Type 17 */
359 dest_dimm->dimm_size = 0;
360 dest_dimm->soc_num = soc;
361 dest_dimm->channel_num = ch;
362 dest_dimm->dimm_num = dimm;
363 continue;
364 } else {
365 /* Ignore DIMM that isn't present and doesn't exist on
366 the board. */
367 continue;
368 }
Eric Laib15946d2023-06-13 10:21:58 +0800369
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800370 dest_dimm->soc_num = soc;
371
372 if (hob->DramType == SPD_TYPE_DDR5) {
373 /* hard-coded memory device type as DDR5 */
374 mem_dev_type = 0x22;
375 data_width = 64;
376 } else {
377 /* hard-coded memory device type as DDR4 */
378 mem_dev_type = 0x1A;
379 data_width = 64;
380 }
381 dimm_info_fill(
382 dest_dimm, src_dimm.DimmSize << 6, mem_dev_type,
383 hob->memFreq, /* replaced by configured_speed_mts */
384 src_dimm.NumRanks,
385 ch, /* for mainboard locator string override */
386 dimm, /* for mainboard locator string override */
387 (const char *)&src_dimm.PartNumber[0],
388 sizeof(src_dimm.PartNumber),
389 (const uint8_t *)&src_dimm.serialNumber[0], data_width,
390 vdd_voltage, true, /* hard-coded as ECC supported */
Eric Laib15946d2023-06-13 10:21:58 +0800391 src_dimm.VendorID, src_dimm.actKeyByte2, 0,
392 get_max_memory_speed(src_dimm.commonTck));
Jonathan Zhang15fc4592023-01-25 11:33:16 -0800393 dimm_num++;
394 }
395 }
396 }
397
398 mem_info->dimm_cnt = index; /* Number of DIMM slots found */
399 printk(BIOS_DEBUG, "%d Installed DIMMs found\n", dimm_num);
400}