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