diff options
Diffstat (limited to 'src/soc/intel/xeon_sp')
-rw-r--r-- | src/soc/intel/xeon_sp/spr/ddr.c | 93 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/hob_display.c | 244 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/include/soc/crashlog.h | 8 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/include/soc/ddr.h | 57 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h | 233 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/include/soc/soc_util.h | 36 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/include/soc/xhci.h | 53 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/romstage.c | 319 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/soc_util.c | 177 | ||||
-rw-r--r-- | src/soc/intel/xeon_sp/spr/upd_display.c | 139 |
10 files changed, 1359 insertions, 0 deletions
diff --git a/src/soc/intel/xeon_sp/spr/ddr.c b/src/soc/intel/xeon_sp/spr/ddr.c new file mode 100644 index 0000000000..ff61a7e8a4 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/ddr.c @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include <soc/ddr.h> + +unsigned int get_ddr_millivolt(unsigned int ddr_voltage) +{ + switch (ddr_voltage) { + case SPD_VDD_DDR4: + return 1200; + case SPD_VDD_DDR5: + return 1100; + default: + return 0; + } +} + +unsigned int get_max_memory_speed(unsigned int commonTck) +{ + if (commonTck <= DDR_8400_TCK_MIN) + return 8400; + else if (commonTck <= DDR_7600_TCK_MIN) + return 7600; + else if (commonTck <= DDR_7200_TCK_MIN) + return 7200; + else if (commonTck <= DDR_6800_TCK_MIN) + return 6800; + else if (commonTck <= DDR_6400_TCK_MIN) + return 6400; + else if (commonTck <= DDR_6000_TCK_MIN) + return 6000; + else if (commonTck <= DDR_5600_TCK_MIN) + return 5600; + else if (commonTck <= DDR_5200_TCK_MIN) + return 5200; + else if (commonTck <= DDR_4800_TCK_MIN) + return 4800; + else if (commonTck <= DDR_4400_TCK_MIN) + return 4400; + else if (commonTck <= DDR_4266_TCK_MIN) + return 4266; + else if (commonTck <= DDR_4200_TCK_MIN) + return 4200; + else if (commonTck <= DDR_4000_TCK_MIN) + return 4000; + else if (commonTck <= DDR_3800_TCK_MIN) + return 3800; + else if (commonTck <= DDR_3733_TCK_MIN) + return 3733; + else if (commonTck <= DDR_3600_TCK_MIN) + return 3600; + else if (commonTck <= DDR_3466_TCK_MIN) + return 3466; + else if (commonTck <= DDR_3400_TCK_MIN) + return 3400; + else if (commonTck <= DDR_3200_TCK_MIN) + return 3200; + else if (commonTck <= DDR_3000_TCK_MIN) + return 3000; + else if (commonTck <= DDR_2933_TCK_MIN) + return 2933; + else if (commonTck <= DDR_2800_TCK_MIN) + return 2800; + else if (commonTck <= DDR_2666_TCK_MIN) + return 2666; + else if (commonTck <= DDR_2600_TCK_MIN) + return 2600; + else if (commonTck <= DDR_2400_TCK_MIN) + return 2400; + else if (commonTck <= DDR_2200_TCK_MIN) + return 2200; + else if (commonTck <= DDR_2133_TCK_MIN) + return 2133; + else if (commonTck <= DDR_2000_TCK_MIN) + return 2000; + else if (commonTck <= DDR_1866_TCK_MIN) + return 1866; + else if (commonTck <= DDR_1800_TCK_MIN) + return 1800; + else if (commonTck <= DDR_1600_TCK_MIN) + return 1600; + else if (commonTck <= DDR_1400_TCK_MIN) + return 1400; + else if (commonTck <= DDR_1333_TCK_MIN) + return 1333; + else if (commonTck <= DDR_1200_TCK_MIN) + return 1200; + else if (commonTck <= DDR_1066_TCK_MIN) + return 1066; + else if (commonTck <= DDR_1000_TCK_MIN) + return 1000; + else + return 800; +} diff --git a/src/soc/intel/xeon_sp/spr/hob_display.c b/src/soc/intel/xeon_sp/spr/hob_display.c new file mode 100644 index 0000000000..cba2d9c8e7 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/hob_display.c @@ -0,0 +1,244 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <fsp/util.h> +#include <hob_cxlnode.h> +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <lib.h> +#include <soc/soc_util.h> + +static const uint8_t fsp_hob_iio_uds_guid[16] = FSP_HOB_IIO_UNIVERSAL_DATA_GUID; +static const uint8_t fsp_hob_memmap_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; +static const uint8_t fsp_hob_cxlnode_guid[16] = FSP_HOB_CXLNODE_GUID; + +struct guid_name_map { + const void *guid; + const char *name; +}; + +static const struct guid_name_map guid_names[] = { + {fsp_hob_iio_uds_guid, "FSP_HOB_IIO_UNIVERSAL_DATA_GUID"}, + {fsp_hob_memmap_guid, "FSP_SYSTEM_MEMORYMAP_HOB_GUID"}, + {fsp_hob_cxlnode_guid, "FSP_HOB_CXLNODE_GUID"}, +}; + +const char *soc_get_guid_name(const uint8_t *guid) +{ + size_t index; + + /* Compare the GUID values in this module */ + for (index = 0; index < ARRAY_SIZE(guid_names); index++) + if (fsp_guid_compare(guid, guid_names[index].guid)) + return guid_names[index].name; + + return NULL; +} + +void soc_display_memmap_hob(const struct SystemMemoryMapHob **hob_addr) +{ + struct SystemMemoryMapHob *hob = (struct SystemMemoryMapHob *)*hob_addr; + + printk(BIOS_DEBUG, "================== MEMORY MAP HOB DATA ==================\n"); + printk(BIOS_DEBUG, "hob: %p, structure size: 0x%lx\n", hob, sizeof(*hob)); + + printk(BIOS_DEBUG, + "\tlowMemBase: 0x%x, lowMemSize: 0x%x, highMemBase: 0x%x, " + "highMemSize: 0x%x\n", + hob->lowMemBase, hob->lowMemSize, hob->highMemBase, hob->highMemSize); + printk(BIOS_DEBUG, "\tmemSize: 0x%x, memFreq: 0x%x\n", hob->memSize, hob->memFreq); + + printk(BIOS_DEBUG, "\tNumChPerMC: %d\n", hob->NumChPerMC); + printk(BIOS_DEBUG, "\tSystemMemoryMapElement Entries: %d, entry size: %ld\n", + hob->numberEntries, sizeof(SYSTEM_MEMORY_MAP_ELEMENT)); + + for (int e = 0; e < hob->numberEntries; ++e) { + const struct SystemMemoryMapElement *mem_element = &hob->Element[e]; + printk(BIOS_DEBUG, + "\t\tmemory_map %d, SocketId: 0x%x, BaseAddress: 0x%x, ElementSize: 0x%x, Type: 0x%x\n", + e, mem_element->SocketId, mem_element->BaseAddress, + mem_element->ElementSize, mem_element->Type); + } + + printk(BIOS_DEBUG, + "^^^ MEMMAP_SOCKET: %ld, ChannelDevice: %ld, MEMMAP_DIMM_DEVICE_INFO_STRUCT: %ld\n", + sizeof(MEMMAP_SOCKET), sizeof(struct ChannelDevice), + sizeof(MEMMAP_DIMM_DEVICE_INFO_STRUCT)); + printk(BIOS_DEBUG, "^^^ Element Offset: %ld\n", + offsetof(SYSTEM_MEMORY_MAP_HOB, Element)); + printk(BIOS_DEBUG, "^^^ Socket Offset: %ld\n", + offsetof(SYSTEM_MEMORY_MAP_HOB, Socket)); + printk(BIOS_DEBUG, "^^^ ChannelInfo Offset: %ld\n", + offsetof(MEMMAP_SOCKET, ChannelInfo)); + printk(BIOS_DEBUG, "^^^ DimmInfo Offset: %ld\n", + offsetof(struct ChannelDevice, DimmInfo)); + printk(BIOS_DEBUG, "^^^ DimmSize Offset: %ld\n", + offsetof(struct DimmDevice, DimmSize)); + + for (int s = 0; s < MAX_SOCKET; ++s) { + if (!hob->Socket[s].SocketEnabled) + continue; + for (int ch = 0; ch < MAX_CH; ++ch) { + if (!hob->Socket[s].ChannelInfo[ch].Enabled) + continue; + for (int dimm = 0; dimm < MAX_DIMM; ++dimm) { + if (!hob->Socket[s].ChannelInfo[ch].DimmInfo[dimm].Present) + continue; + printk(BIOS_DEBUG, + "\tsocket: %d, ch: %d, dimm: %d, enabled: %d, DimmSize: 0x%x\n", + s, ch, dimm, + hob->Socket[s].ChannelInfo[ch].DimmInfo[dimm].Enabled, + hob->Socket[s].ChannelInfo[ch].DimmInfo[dimm].DimmSize); + } + } + } + + printk(BIOS_DEBUG, "\tBiosFisVersion: 0x%x\n", hob->BiosFisVersion); + printk(BIOS_DEBUG, "\tMmiohBase: 0x%x\n", hob->MmiohBase); + + hexdump(hob, sizeof(*hob)); +} + +void soc_display_iio_universal_data_hob(const IIO_UDS *hob) +{ + printk(BIOS_DEBUG, "===================== IIO_UDS HOB DATA =====================\n"); + printk(BIOS_DEBUG, "hob: %p, structure size: 0x%lx\n", hob, sizeof(*hob)); + + printk(BIOS_DEBUG, "\t===================== SYSTEM STATUS =====================\n"); + printk(BIOS_DEBUG, "\tnumCpus: 0x%x\n", hob->SystemStatus.numCpus); + printk(BIOS_DEBUG, "\ttolmLimit: 0x%x\n", hob->SystemStatus.tolmLimit); + + printk(BIOS_DEBUG, "\t===================== PLATFORM DATA =====================\n"); + printk(BIOS_DEBUG, "\tPlatGlobalIoBase: 0x%x\n", hob->PlatformData.PlatGlobalIoBase); + printk(BIOS_DEBUG, "\tPlatGlobalIoLimit: 0x%x\n", hob->PlatformData.PlatGlobalIoLimit); + printk(BIOS_DEBUG, "\tPlatGlobalMmio32Base: 0x%x\n", + hob->PlatformData.PlatGlobalMmio32Base); + printk(BIOS_DEBUG, "\tPlatGlobalMmio32Limit: 0x%x\n", + hob->PlatformData.PlatGlobalMmio32Limit); + printk(BIOS_DEBUG, "\tPlatGlobalMmio64Base: 0x%llx\n", + hob->PlatformData.PlatGlobalMmio64Base); + printk(BIOS_DEBUG, "\tPlatGlobalMmio64Limit: 0x%llx\n", + hob->PlatformData.PlatGlobalMmio64Limit); + printk(BIOS_DEBUG, "\tMemTsegSize: 0x%x\n", hob->PlatformData.MemTsegSize); + printk(BIOS_DEBUG, "\tPciExpressBase: 0x%llx\n", hob->PlatformData.PciExpressBase); + printk(BIOS_DEBUG, "\tPciExpressSize: 0x%x\n", hob->PlatformData.PciExpressSize); + printk(BIOS_DEBUG, "\tMemTolm: 0x%x\n", hob->PlatformData.MemTolm); + printk(BIOS_DEBUG, "\tnumofIIO: 0x%x\n", hob->PlatformData.numofIIO); + printk(BIOS_DEBUG, "\tMaxBusNumber: 0x%x\n", hob->PlatformData.MaxBusNumber); + printk(BIOS_DEBUG, "\tIoGranularity: 0x%x\n", hob->PlatformData.IoGranularity); + printk(BIOS_DEBUG, "\tMmiolGranularity: 0x%x\n", hob->PlatformData.MmiolGranularity); + printk(BIOS_DEBUG, "\tMmiohGranularity: hi: 0x%x, lo:0x%x\n", + hob->PlatformData.MmiohGranularity.hi, hob->PlatformData.MmiohGranularity.lo); + + for (uint8_t s = 0; s < hob->PlatformData.numofIIO; ++s) { + printk(BIOS_DEBUG, "\t============ Socket %d Info ================\n", s); + printk(BIOS_DEBUG, "\tValid: 0x%x\n", hob->PlatformData.IIO_resource[s].Valid); + printk(BIOS_DEBUG, "\tSocketID: 0x%x\n", + hob->PlatformData.IIO_resource[s].SocketID); + printk(BIOS_DEBUG, "\tBusBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].BusBase); + printk(BIOS_DEBUG, "\tBusLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].BusLimit); + printk(BIOS_DEBUG, "\tPciResourceIoBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceIoBase); + printk(BIOS_DEBUG, "\tPciResourceIoLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].PciResourceIoLimit); + printk(BIOS_DEBUG, "\tIoApicBase: 0x%x\n", + hob->PlatformData.IIO_resource[s].IoApicBase); + printk(BIOS_DEBUG, "\tIoApicLimit: 0x%x\n", + hob->PlatformData.IIO_resource[s].IoApicLimit); + printk(BIOS_DEBUG, "\tMmio32Base: 0x%x\n", + hob->PlatformData.IIO_resource[s].Mmio32Base); + printk(BIOS_DEBUG, "\tMmio32Limit: 0x%x\n", + hob->PlatformData.IIO_resource[s].Mmio32Limit); + printk(BIOS_DEBUG, "\tMmio64Base: 0x%llx\n", + hob->PlatformData.IIO_resource[s].Mmio64Base); + printk(BIOS_DEBUG, "\tMmio64Limit: 0x%llx\n", + hob->PlatformData.IIO_resource[s].Mmio64Limit); + + printk(BIOS_DEBUG, "\t============ Stack Info ================\n"); + for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) { + const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x]; + printk(BIOS_DEBUG, "\t\t========== Stack %d ===============\n", x); + printk(BIOS_DEBUG, "\t\tPersonality: 0x%x\n", ri->Personality); + printk(BIOS_DEBUG, "\t\tBusBase: 0x%x\n", ri->BusBase); + printk(BIOS_DEBUG, "\t\tBusLimit: 0x%x\n", ri->BusLimit); + printk(BIOS_DEBUG, "\t\tIoBase: 0x%x\n", ri->IoBase); + printk(BIOS_DEBUG, "\t\tIoLimit: 0x%x\n", ri->IoLimit); + printk(BIOS_DEBUG, "\t\tPciResourceIoBase: 0x%x\n", + ri->PciResourceIoBase); + printk(BIOS_DEBUG, "\t\tPciResourceIoLimit: 0x%x\n", + ri->PciResourceIoLimit); + printk(BIOS_DEBUG, "\t\tIoApicBase: 0x%x\n", ri->IoApicBase); + printk(BIOS_DEBUG, "\t\tIoApicLimit: 0x%x\n", ri->IoApicLimit); + printk(BIOS_DEBUG, "\t\tMmio32Base: 0x%x\n", ri->Mmio32Base); + printk(BIOS_DEBUG, "\t\tMmio32Limit: 0x%x\n", ri->Mmio32Limit); + printk(BIOS_DEBUG, "\t\tPciResourceMem32Base: 0x%x\n", + ri->PciResourceMem32Base); + printk(BIOS_DEBUG, "\t\tPciResourceMem32Limit: 0x%x\n", + ri->PciResourceMem32Limit); + printk(BIOS_DEBUG, "\t\tMmio64Base: 0x%llx\n", ri->Mmio64Base); + printk(BIOS_DEBUG, "\t\tMmio64Limit: 0x%llx\n", ri->Mmio64Limit); + printk(BIOS_DEBUG, "\t\tPciResourceMem64Base: 0x%llx\n", + ri->PciResourceMem64Base); + printk(BIOS_DEBUG, "\t\tPciResourceMem64Limit: 0x%llx\n", + ri->PciResourceMem64Limit); + printk(BIOS_DEBUG, "\t\tVtdBarAddress: 0x%x\n", ri->VtdBarAddress); + } + + printk(BIOS_DEBUG, "\t============ PcieInfo ================\n"); + IIO_RESOURCE_INSTANCE iio_resource = hob->PlatformData.IIO_resource[s]; + for (int p = 0; p < NUMBER_PORTS_PER_SOCKET; ++p) { + printk(BIOS_DEBUG, "\t\tPort: %d, Device: 0x%x, Function: 0x%x\n", p, + iio_resource.PcieInfo.PortInfo[p].Device, + iio_resource.PcieInfo.PortInfo[p].Function); + } + } + + hexdump(hob, sizeof(*hob)); +} + +static void soc_display_cxlnode_hob(const CXL_NODE_SOCKET *hob) +{ + printk(BIOS_DEBUG, "===================== CXLNODE HOB DATA =====================\n"); + printk(BIOS_DEBUG, "hob: %p, structure size: 0x%lx\n", hob, sizeof(*hob) * MAX_SOCKET); + + for (uint8_t skt_id = 0; skt_id < MAX_SOCKET; skt_id++) { + printk(BIOS_DEBUG, "\tSocket:%d, CxlNodeCount: 0x%x\n", skt_id, + hob[skt_id].CxlNodeCount); + for (uint8_t i = 0; i < hob[skt_id].CxlNodeCount; ++i) { + printk(BIOS_DEBUG, "\tCxlNodeInfo[%d]:\n", i); + const CXL_NODE_INFO node = hob[skt_id].CxlNodeInfo[i]; + printk(BIOS_DEBUG, "\t\tSerialNumber: 0x%llx\n", node.SerialNumber); + printk(BIOS_DEBUG, "\t\tVendorId: 0x%x\n", node.VendorId); + printk(BIOS_DEBUG, "\t\tAttr: 0x%x\n", node.Attr); + printk(BIOS_DEBUG, "\t\tAddress: 0x%x\n", node.Address); + printk(BIOS_DEBUG, "\t\tSize: 0x%x\n", node.Size); + printk(BIOS_DEBUG, "\t\tWays: 0x%x\n", node.Ways); + printk(BIOS_DEBUG, "\t\tSocketBitmap: 0x%x\n", node.SocketBitmap); + printk(BIOS_DEBUG, + "\t\tPerfData format: RdLatency(0.1ns), WrLatency(0.1ns), RdBW(100MB/s), WrBW(100MB/s)\n"); + printk(BIOS_DEBUG, + "\t\tEfiMemType and PerfData are invalid for SPR-SP.\n"); + } + } + + hexdump(hob, sizeof(*hob) * MAX_SOCKET); +} + +void soc_display_hob(const struct hob_header *hob) +{ + uint8_t *guid; + + if (hob->type != HOB_TYPE_GUID_EXTENSION) + return; + + guid = (uint8_t *)fsp_hob_header_to_resource(hob); + + if (fsp_guid_compare(guid, fsp_hob_iio_uds_guid)) + soc_display_iio_universal_data_hob((const IIO_UDS *)(guid + 16)); + else if (fsp_guid_compare(guid, fsp_hob_memmap_guid)) + soc_display_memmap_hob((const struct SystemMemoryMapHob **)(guid + 16)); + else if (fsp_guid_compare(guid, fsp_hob_cxlnode_guid)) + soc_display_cxlnode_hob((const CXL_NODE_SOCKET *)(guid + 16)); +} diff --git a/src/soc/intel/xeon_sp/spr/include/soc/crashlog.h b/src/soc/intel/xeon_sp/spr/include/soc/crashlog.h new file mode 100644 index 0000000000..ff47232138 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/include/soc/crashlog.h @@ -0,0 +1,8 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_CRASHLOG_H_ +#define _SOC_CRASHLOG_H_ + +void disable_cpu_crashlog(void); + +#endif /* _SOC_CRASHLOG_H_ */ diff --git a/src/soc/intel/xeon_sp/spr/include/soc/ddr.h b/src/soc/intel/xeon_sp/spr/include/soc/ddr.h new file mode 100644 index 0000000000..f2dc5c8998 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/include/soc/ddr.h @@ -0,0 +1,57 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _SPR_DDR_H_ +#define _SPR_DDR_H_ + +#include <types.h> + +/* SPD Byte 11: Module Nominal Voltage + * currently DDR4 only supports 1.2V, DDR5 only supports 1.1V. */ +#define SPD_VDD_DDR4 3 +#define SPD_VDD_DDR5 0 +#define SPD_TYPE_DDR5 0x12 + +/* DDR_*_TCK_MIN are in picoseconds */ +#define DDR_1000_TCK_MIN 2000 +#define DDR_1066_TCK_MIN 1875 +#define DDR_1200_TCK_MIN 1667 +#define DDR_1333_TCK_MIN 1500 +#define DDR_1400_TCK_MIN 1429 +#define DDR_1600_TCK_MIN 1250 +#define DDR_1800_TCK_MIN 1110 +#define DDR_1866_TCK_MIN 1071 +#define DDR_2000_TCK_MIN 1000 +#define DDR_2133_TCK_MIN 938 +#define DDR_2200_TCK_MIN 909 +#define DDR_2400_TCK_MIN 833 +#define DDR_2600_TCK_MIN 769 +#define DDR_2666_TCK_MIN 750 +#define DDR_2800_TCK_MIN 714 +#define DDR_2933_TCK_MIN 682 +#define DDR_3000_TCK_MIN 667 +#define DDR_3200_TCK_MIN 625 +#define DDR_3400_TCK_MIN 589 +#define DDR_3466_TCK_MIN 577 +#define DDR_3600_TCK_MIN 556 +#define DDR_3733_TCK_MIN 536 +#define DDR_3800_TCK_MIN 527 +#define DDR_4000_TCK_MIN 500 +#define DDR_4200_TCK_MIN 477 +#define DDR_4266_TCK_MIN 469 +#define DDR_4400_TCK_MIN 455 +#define DDR_4800_TCK_MIN 417 +#define DDR_5200_TCK_MIN 385 +#define DDR_5600_TCK_MIN 358 +#define DDR_6000_TCK_MIN 334 +#define DDR_6400_TCK_MIN 313 +#define DDR_6800_TCK_MIN 295 +#define DDR_7200_TCK_MIN 278 +#define DDR_7600_TCK_MIN 264 +#define DDR_8000_TCK_MIN 250 +#define DDR_8400_TCK_MIN 239 + +unsigned int get_max_memory_speed(unsigned int commonTck); +unsigned int get_ddr_millivolt(unsigned int ddr_voltage); +bool mainboard_dimm_slot_exists(uint8_t socket, uint8_t channel, uint8_t slot); + +#endif /* _SPR_DDR_H_ */ diff --git a/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h b/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h new file mode 100644 index 0000000000..fba3c683e8 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/include/soc/pci_devs.h @@ -0,0 +1,233 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_PCI_DEVS_H_ +#define _SOC_PCI_DEVS_H_ + +#include <device/pci_def.h> +#include <types.h> + +#define _SA_DEVFN(slot) PCI_DEVFN(SA_DEV_SLOT_##slot, 0) +#define _PCH_DEVFN(slot, func) PCI_DEVFN(PCH_DEV_SLOT_##slot, func) + +#if !defined(__SIMPLE_DEVICE__) +#include <device/device.h> +#define _SA_DEV(slot) pcidev_path_on_root_debug(_SA_DEVFN(slot), __func__) +#define _PCH_DEV(slot, func) pcidev_path_on_root_debug(_PCH_DEVFN(slot, func), __func__) +#else +#define _SA_DEV(slot) PCI_DEV(0, SA_DEV_SLOT_##slot, 0) +#define _PCH_DEV(slot, func) PCI_DEV(0, PCH_DEV_SLOT_##slot, func) +#endif + +#define UNCORE_BUS_0 0 +#define UNCORE_BUS_1 1 + +/* UBOX Registers [B:30, D:0, F:1] */ +#define UBOX_DECS_DEV 0 +#define UBOX_URACU_FUNC 1 +#define SMM_FEATURE_CONTROL 0x8c +#define SMM_CODE_CHK_EN BIT(2) +#define SMM_FEATURE_CONTROL_LOCK BIT(0) + +/* CHA registers [B:31, D:29, F:0/F:1] + * SAD is the previous xeon_sp register name. Keep defines for shared code. + */ +#define CHA_DEV 29 + +#define SAD_ALL_DEV CHA_DEV +#define SAD_ALL_FUNC 0 +#define SAD_ALL_PAM0123_CSR 0x80 +#define SAD_ALL_PAM456_CSR 0x84 + +#if !defined(__SIMPLE_DEVICE__) +#define _PCU_DEV(bus, func) pcidev_path_on_bus(bus, PCI_DEVFN(PCU_DEV, func)) +#else +#define _PCU_DEV(bus, func) PCI_DEV(bus, PCU_DEV, func) +#endif + +/* PCU [B:31, D:30, F:0->F:6] */ +#define PCU_IIO_STACK UNCORE_BUS_1 +#define PCU_DEV 30 + +#define PCU_CR0_FUN 0 +#define PCU_DEV_CR0(bus) _PCU_DEV(bus, PCU_CR0_FUN) +#define PCU_CR0_PLATFORM_INFO 0xa8 +#define PCU_CR0_TURBO_ACTIVATION_RATIO 0xb0 +#define TURBO_ACTIVATION_RATIO_LOCK BIT(31) +#define PCU_CR0_P_STATE_LIMITS 0xd8 +#define P_STATE_LIMITS_LOCK BIT(31) +#define PCU_CR0_PACKAGE_RAPL_LIMIT_LWR 0xe8 +#define PCU_CR0_PACKAGE_RAPL_LIMIT_UPR (PCU_CR0_PACKAGE_RAPL_LIMIT_LWR + 4) +#define PKG_PWR_LIM_LOCK_UPR BIT(31) +#define PCU_CR0_PMAX 0xf0 +#define PMAX_LOCK BIT(31) +#define PCU_CR0_VR_CURRENT_CONFIG_CFG 0xf8 +#define VR_CURRENT_CONFIG_LOCK BIT(31) + +#define PCU_CR1_FUN 1 +#define PCU_DEV_CR1(bus) _PCU_DEV(bus, PCU_CR1_FUN) +#define PCU_CR1_BIOS_MB_DATA_REG 0x8c + +#define PCU_CR1_BIOS_MB_INTERFACE_REG 0x90 +#define BIOS_MB_RUN_BUSY_MASK BIT(31) +#define BIOS_MB_CMD_MASK 0xff +#define BIOS_CMD_READ_PCU_MISC_CFG 0x5 +#define BIOS_CMD_WRITE_PCU_MISC_CFG 0x6 +#define BIOS_ERR_INVALID_CMD 0x01 + +#define PCU_CR1_BIOS_RESET_CPL_REG 0x94 +#define RST_CPL1_MASK BIT(1) +#define RST_CPL2_MASK BIT(2) +#define RST_CPL3_MASK BIT(3) +#define RST_CPL4_MASK BIT(4) +#define PCODE_INIT_DONE1_MASK BIT(9) +#define PCODE_INIT_DONE2_MASK BIT(10) +#define PCODE_INIT_DONE3_MASK BIT(11) +#define PCODE_INIT_DONE4_MASK BIT(12) + +#define PCU_CR1_DESIRED_CORES_CFG2_REG 0xbc +#define PCU_CR1_DESIRED_CORES_CFG2_REG_LOCK_MASK BIT(31) + +#define PCU_CR2_FUN 2 +#define PCU_DEV_CR2(bus) _PCU_DEV(bus, PCU_CR2_FUN) +#define PCU_CR2_DRAM_POWER_INFO_LWR 0xa8 +#define PCU_CR2_DRAM_POWER_INFO_UPR (PCU_CR2_DRAM_POWER_INFO_LWR + 4) +#define DRAM_POWER_INFO_LOCK_UPR BIT(31) + +#define PCU_CR2_DRAM_PLANE_POWER_LIMIT_LWR 0xf0 +#define PCU_CR2_DRAM_PLANE_POWER_LIMIT_UPR (PCU_CR2_DRAM_PLANE_POWER_LIMIT_LWR + 4) +#define PP_PWR_LIM_LOCK_UPR BIT(31) + +#define PCU_CR3_FUN 3 +#define PCU_CR3_CAPID4 0x94 +#define ERR_SPOOFING_DIS 1 +#define PCU_DEV_CR3(bus) _PCU_DEV(bus, PCU_CR3_FUN) +#define PCU_CR3_CONFIG_TDP_CONTROL 0xd8 +#define TDP_LOCK BIT(31) +#define PCU_CR3_FLEX_RATIO 0xa0 +#define OC_LOCK BIT(20) + +#define PCU_CR4_FUN 4 +#define PCU_VIRAL_CONTROL 0x84 +#define PCU_FW_ERR_EN (1 << 10) +#define PCU_UC_ERR_EN (1 << 9) +#define PCU_HW_ERR_EN (1 << 8) +#define PCU_EMCA_MODE (1 << 2) + +#define PCU_CR6_FUN 6 +#define PCU_DEV_CR6(bus) _PCU_DEV(bus, PCU_CR6_FUN) +#define PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_LWR 0xa8 +#define PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_UPR (PCU_CR6_PLATFORM_RAPL_LIMIT_CFG_LWR + 4) +#define PLT_PWR_LIM_LOCK_UPR BIT(31) +#define PCU_CR6_PLATFORM_POWER_INFO_CFG_LWR 0xb0 +#define PCU_CR6_PLATFORM_POWER_INFO_CFG_UPR (PCU_CR6_PLATFORM_POWER_INFO_CFG_LWR + 4) +#define PLT_PWR_INFO_LOCK_UPR BIT(31) + +/* Memory Map/VTD Device Functions + * These are available in each IIO stack + */ +#define MMAP_VTD_DEV 0x0 +#define MMAP_VTD_FUNC 0x0 + +#define VTD_TOLM_CSR 0xd0 +#define VTD_TSEG_BASE_CSR 0xa8 +#define VTD_TSEG_LIMIT_CSR 0xac +#define VTD_EXT_CAP_LOW 0x10 +#define VTD_MMCFG_BASE_CSR 0x90 +#define VTD_MMCFG_LIMIT_CSR 0x98 +#define VTD_TOHM_CSR 0xc8 +#define VTD_MMIOL_CSR 0xd8 +#define VTD_NCMEM_BASE_CSR 0xe0 +#define VTD_NCMEM_LIMIT_CSR 0xe8 +#define VTD_LTDPR 0x290 + +#define VMD_DEV_NUM 0x00 +#define VMD_FUNC_NUM 0x05 + +#define MMAP_VTD_CFG_REG_DEVID 0x09a2 +#define MMAP_VTD_STACK_CFG_REG_DEVID 0x09a2 +#define VTD_DEV_NUM 0x0 +#define VTD_FUNC_NUM 0x0 + +#if !defined(__SIMPLE_DEVICE__) +#define VTD_DEV(bus) pcidev_path_on_bus((bus), PCI_DEVFN(VTD_DEV_NUM, VTD_FUNC_NUM)) +#else +#define VTD_DEV(bus) PCI_DEV((bus), VTD_DEV_NUM, VTD_FUNC_NUM) +#endif + +/* PCH Device info */ + +#define XHCI_BUS_NUMBER 0x0 +#define PCH_DEV_SLOT_XHCI 0x14 +#define XHCI_FUNC_NUM 0x0 +#define PCH_DEVFN_XHCI _PCH_DEVFN(XHCI, 0) +#define PCH_DEV_XHCI _PCH_DEV(XHCI, 0) +#define PCH_DEVFN_THERMAL _PCH_DEVFN(XHCI, 2) + + +#define PCH_DEV_SLOT_CSE 0x16 +#define PCH_DEVFN_CSE _PCH_DEVFN(CSE, 0) +#define PCH_DEVFN_CSE_2 _PCH_DEVFN(CSE, 1) +#define PCH_DEVFN_CSE_3 _PCH_DEVFN(CSE, 4) +#define PCH_DEV_CSE _PCH_DEV(CSE, 0) +#define PCH_DEV_CSE_2 _PCH_DEV(CSE, 1) +#define PCH_DEV_CSE_3 _PCH_DEV(CSE, 4) + +#define PCH_DEV_SLOT_LPC 0x1f +#define PCH_DEVFN_LPC _PCH_DEVFN(LPC, 0) +#define PCH_DEVFN_P2SB _PCH_DEVFN(LPC, 1) +#define PCH_DEVFN_PMC _PCH_DEVFN(LPC, 2) +#define PCH_DEVFN_SMBUS _PCH_DEVFN(LPC, 4) +#define PCH_DEVFN_SPI _PCH_DEVFN(LPC, 5) +#define PCH_DEV_LPC _PCH_DEV(LPC, 0) +#define PCH_DEV_P2SB _PCH_DEV(LPC, 1) +#define PCH_DEV_PMC _PCH_DEV(LPC, 2) +#define PCH_DEV_SMBUS _PCH_DEV(LPC, 4) +#define PCH_DEV_SPI _PCH_DEV(LPC, 5) + +#define HPET_BUS_NUM 0x0 +#define HPET_DEV_NUM PCH_DEV_SLOT_LPC +#define HPET0_FUNC_NUM 0x00 + +#define PCH_IOAPIC_BUS_NUMBER 0xF0 +#define PCH_IOAPIC_DEV_NUM 0x1F +#define PCH_IOAPIC_FUNC_NUM 0x00 + +// ========== IOAPIC Definitions for DMAR/ACPI ======== +#define PCH_IOAPIC_ID 0x08 + +/* Root port Registers */ + +/* IEH */ +#define IEH_EXT_CAP_ID 0x7 /* At 0x160 */ +#define GSYSEVTCTL 0x104 /* Offset from IEH_EXT_CAP_ID */ +#define CE_ERR_UNMSK 1 +#define NON_FATAL_UNMSK (1 << 1) +#define FATAL_UNMSK (1 << 2) +#define GSYSEVTMAP 0x108 /* Offset from IEH_EXT_CAP_ID */ +#define CE_SMI 1 +#define NF_SMI (1 << 2) +#define FA_SMI (1 << 4) + + +#define DMIRCBAR 0x50 +#define DMI3_DEVID 0x2020 +#define PCIE_ROOTCTL 0x5c +#define ERRINJCON 0x198 + +// IIO DFX Global D7F7 registers +#define IIO_DFX_TSWCTL0 0x30c +#define IIO_DFX_LCK_CTL 0x504 + +// XHCI register +#define SYS_BUS_CFG2 0x44 + +/* MSM registers */ +#define MSM_BUS 0xF2 +#define MSM_DEV 3 +#define MSM_FUN 0 +#define MSM_FUN_PMON 1 +#define CRASHLOG_CTL 0x1B8 +#define BIOS_CRASHLOG_CTL 0x158 +#define CRASHLOG_CTL_DIS BIT(2) + +#endif /* _SOC_PCI_DEVS_H_ */ diff --git a/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h b/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h new file mode 100644 index 0000000000..4539991d55 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/include/soc/soc_util.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef _SOC_UTIL_H_ +#define _SOC_UTIL_H_ + +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <hob_cxlnode.h> +#include <hob_systeminfo.h> +#include <hob_enhancedwarningloglib.h> + +const struct SystemMemoryMapHob *get_system_memory_map(void); +const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num); + +uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack); + +bool is_iio_cxl_stack_res(const STACK_RES *res); + +void soc_display_iio_universal_data_hob(const IIO_UDS *hob); +void soc_display_memmap_hob(const struct SystemMemoryMapHob **hob_addr); + +const CXL_NODE_SOCKET *get_cxl_node(void); +uint8_t get_cxl_node_count(void); + +const SYSTEM_INFO_VAR *get_system_info_hob(void); + +const EWL_PRIVATE_DATA *get_ewl_hob(void); + +uint32_t get_ubox_busno(uint32_t socket, uint8_t offset); +uint32_t get_socket_ubox_busno(uint32_t socket); + +void check_fsp_error(void); + +void mainboard_fsp_error_handle(void); + +#endif /* _SOC_UTIL_H_ */ diff --git a/src/soc/intel/xeon_sp/spr/include/soc/xhci.h b/src/soc/intel/xeon_sp/spr/include/soc/xhci.h new file mode 100644 index 0000000000..005a8e1b0b --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/include/soc/xhci.h @@ -0,0 +1,53 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#ifndef _XHCI_H_ +#define _XHCI_H_ + +#include <types.h> + +#define USB2_OC_PIN_0 0x90A4 +#define USB2_OC_PIN_1 0x90A8 +#define USB2_OC_PIN_2 0x90AC +#define USB2_OC_PIN_3 0x90B0 +#define USB2_OC_PIN_4 0x90B4 +#define USB2_OC_PIN_5 0x90B8 +#define USB2_OC_PIN_6 0x90BC +#define USB2_OC_PIN_7 0x90C0 + +#define USB3_OC_PIN_0 0x9124 +#define USB3_OC_PIN_1 0x9128 +#define USB3_OC_PIN_2 0x912C +#define USB3_OC_PIN_3 0x9130 +#define USB3_OC_PIN_4 0x9134 +#define USB3_OC_PIN_5 0x9138 +#define USB3_OC_PIN_6 0x913C +#define USB3_OC_PIN_7 0x9140 + +#define USB_PORT_0 BIT(0) +#define USB_PORT_1 BIT(1) +#define USB_PORT_2 BIT(2) +#define USB_PORT_3 BIT(3) +#define USB_PORT_4 BIT(4) +#define USB_PORT_5 BIT(5) +#define USB_PORT_6 BIT(6) +#define USB_PORT_7 BIT(7) +#define USB_PORT_8 BIT(8) +#define USB_PORT_9 BIT(9) +#define USB_PORT_10 BIT(10) +#define USB_PORT_11 BIT(11) +#define USB_PORT_12 BIT(12) +#define USB_PORT_13 BIT(13) +#define USB_PORT_14 BIT(14) +#define USB_PORT_15 BIT(15) +#define USB_PORT_NONE 0 +#define OCCFGDONE BIT(31) + +struct usb_oc_mapping { + uint32_t pin; + uint32_t port; +}; + +void write_usb_oc_mapping(const struct usb_oc_mapping *config, uint8_t pins); +void lock_oc_cfg(bool lock); + +#endif /* _XHCI_H_ */ diff --git a/src/soc/intel/xeon_sp/spr/romstage.c b/src/soc/intel/xeon_sp/spr/romstage.c new file mode 100644 index 0000000000..b49972eee1 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/romstage.c @@ -0,0 +1,319 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <cpu/cpu.h> +#include <cpu/intel/cpu_ids.h> +#include <arch/romstage.h> +#include <console/console.h> +#include <cbmem.h> +#include <drivers/vpd/vpd.h> +#include <drivers/ocp/include/vpd.h> +#include <security/intel/txt/txt.h> +#include <fsp/api.h> +#include <fsp/util.h> +#include <hob_iiouds.h> +#include <hob_memmap.h> +#include <soc/romstage.h> +#include <soc/pci_devs.h> +#include <soc/intel/common/smbios.h> +#include <string.h> +#include <soc/soc_util.h> +#include <soc/ddr.h> + +#include "chip.h" + +/* Initialize to all zero first */ +static UPD_IIO_PCIE_PORT_CONFIG spr_iio_bifur_table[CONFIG_MAX_SOCKET_UPD]; +static UINT8 deemphasis_list[CONFIG_MAX_SOCKET_UPD * MAX_IIO_PORTS_PER_SOCKET]; + +void __weak mainboard_memory_init_params(FSPM_UPD *mupd) +{ + /* Default weak implementation */ +} + +bool __weak mainboard_dimm_slot_exists(uint8_t socket, uint8_t channel, uint8_t dimm) +{ + return false; +} + +/* + * Search from VPD_RW first then VPD_RO for UPD config variables, + * overwrites them from VPD if it's found. + */ +static void config_upd_from_vpd(FSPM_UPD *mupd) +{ + uint8_t val; + int val_int, cxl_mode; + + /* Send FSP log message to SOL */ + if (vpd_get_bool(FSP_LOG, VPD_RW_THEN_RO, &val)) + mupd->FspmConfig.SerialIoUartDebugEnable = val; + else { + printk(BIOS_INFO, + "Not able to get VPD %s, default set " + "SerialIoUartDebugEnable to %d\n", + FSP_LOG, FSP_LOG_DEFAULT); + mupd->FspmConfig.SerialIoUartDebugEnable = FSP_LOG_DEFAULT; + } + + if (mupd->FspmConfig.SerialIoUartDebugEnable) { + /* FSP memory debug log level */ + if (vpd_get_int(FSP_MEM_LOG_LEVEL, VPD_RW_THEN_RO, &val_int)) { + if (val_int < 0 || val_int > 4) { + printk(BIOS_DEBUG, + "Invalid serialDebugMsgLvl value from VPD: " + "%d\n", + val_int); + val_int = FSP_MEM_LOG_LEVEL_DEFAULT; + } + printk(BIOS_DEBUG, "Setting serialDebugMsgLvl to %d\n", val_int); + mupd->FspmConfig.serialDebugMsgLvl = (uint8_t)val_int; + } else { + printk(BIOS_INFO, + "Not able to get VPD %s, default set " + "DebugPrintLevel to %d\n", + FSP_MEM_LOG_LEVEL, FSP_MEM_LOG_LEVEL_DEFAULT); + mupd->FspmConfig.serialDebugMsgLvl = FSP_MEM_LOG_LEVEL_DEFAULT; + } + /* If serialDebugMsgLvl less than 1, disable FSP memory train results */ + if (mupd->FspmConfig.serialDebugMsgLvl <= 1) { + printk(BIOS_DEBUG, "Setting serialDebugMsgLvlTrainResults to 0\n"); + mupd->FspmConfig.serialDebugMsgLvlTrainResults = 0x0; + } + } + + /* FSP Dfx PMIC Secure mode */ + if (vpd_get_int(FSP_PMIC_SECURE_MODE, VPD_RW_THEN_RO, &val_int)) { + if (val_int < 0 || val_int > 2) { + printk(BIOS_DEBUG, + "Invalid PMIC secure mode value from VPD: " + "%d\n", + val_int); + val_int = FSP_PMIC_SECURE_MODE_DEFAULT; + } + printk(BIOS_DEBUG, "Setting PMIC secure mode to %d\n", val_int); + mupd->FspmConfig.DfxPmicSecureMode = (uint8_t)val_int; + } else { + printk(BIOS_INFO, + "Not able to get VPD %s, default set " + "PMIC secure mode to %d\n", + FSP_PMIC_SECURE_MODE, FSP_PMIC_SECURE_MODE_DEFAULT); + mupd->FspmConfig.DfxPmicSecureMode = FSP_PMIC_SECURE_MODE_DEFAULT; + } + + cxl_mode = get_cxl_mode_from_vpd(); + if (cxl_mode == CXL_SYSTEM_MEMORY || cxl_mode == CXL_SPM) + mupd->FspmConfig.DfxCxlType3LegacyEn = 1; + else /* Disable CXL */ + mupd->FspmConfig.DfxCxlType3LegacyEn = 0; + + if (CONFIG(INTEL_TXT)) { + /* Configure for error injection test */ + mupd->FspmConfig.DFXEnable = skip_intel_txt_lockdown() ? 1 : 0; + } +} + +/* Initialize non-zero default UPD values for IIO */ +static void initialize_iio_upd(FSPM_UPD *mupd) +{ + unsigned int port, socket; + + mupd->FspmConfig.IioPcieConfigTablePtr = (UINT32)spr_iio_bifur_table; + mupd->FspmConfig.IioPcieConfigTableNumber = CONFIG_MAX_SOCKET_UPD; + UPD_IIO_PCIE_PORT_CONFIG *PciePortConfig = + (UPD_IIO_PCIE_PORT_CONFIG *)spr_iio_bifur_table; + + /* Initialize non-zero default UPD values */ + for (socket = 0; socket < CONFIG_MAX_SOCKET_UPD; socket++) { + for (port = 0; port < MAX_IIO_PORTS_PER_SOCKET; port++) { + PciePortConfig[socket].PcieMaxPayload[port] = 0x7; /* Auto */ + PciePortConfig[socket].DfxDnTxPresetGen3[port] = 0xff; /* Auto */ + } + PciePortConfig[socket].PcieGlobalAspm = 0x1; /* Enable ASPM */ + PciePortConfig[socket].PcieMaxReadRequestSize = 0x5; + } + + mupd->FspmConfig.DeEmphasisPtr = (UINT32)deemphasis_list; + mupd->FspmConfig.DeEmphasisNumber = CONFIG_MAX_SOCKET_UPD * MAX_IIO_PORTS_PER_SOCKET; + UINT8 *DeEmphasisConfig = (UINT8 *)deemphasis_list; + + for (port = 0; port < CONFIG_MAX_SOCKET_UPD * MAX_IIO_PORTS_PER_SOCKET; port++) + DeEmphasisConfig[port] = 0x1; +} + +void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version) +{ + FSP_M_CONFIG *m_cfg = &mupd->FspmConfig; + const config_t *config = config_of_soc(); + + m_cfg->DebugPrintLevel = 0xF; + + m_cfg->DirectoryModeEn = 0x2; + const u8 KtiFpgaEnable[] = {0x2, 0x2, 0x2, 0x2, 0x1, 0x1, 0x1, 0x1}; + memcpy(m_cfg->KtiFpgaEnable, KtiFpgaEnable, sizeof(m_cfg->KtiFpgaEnable)); + + m_cfg->TscSyncEn = 0x1; + + m_cfg->mmiohBase = 0x2000; + m_cfg->mmiohSize = 0x3; + + m_cfg->BoardTypeBitmask = 0x11111133; + + m_cfg->X2apic = config->x2apic; + + printk(BIOS_INFO, "m_cfg->X2apic = 0x%x config->x2apic = 0x%x\n", m_cfg->X2apic, + config->x2apic); + + + m_cfg->serialDebugMsgLvl = 0x3; + + m_cfg->VtdSupport = config->vtd_support; + + m_cfg->SerialIoUartDebugIoBase = 0x3F8; + + mupd->FspmConfig.AttemptFastBoot = 1; + mupd->FspmConfig.AttemptFastBootCold = 1; + + /* Set Patrol Scrub UPD */ + mupd->FspmConfig.PatrolScrubNotify = 0x1; /* 1:Enable at ReadyToBootFsp() */ + mupd->FspmConfig.PatrolScrub = 0x2; /* 2:Enable during + NotifyPhase(EnumInitPhaseReadyToBoot) */ + mupd->FspmConfig.ErrorCheckScrub = 1; /* Enable/Disable DDR5 Error Check + and Scrub (ECS) in FSP */ + mupd->FspmConfig.PatrolScrubAddrMode = 1; /* 1:System Physical Address */ + mupd->FspmConfig.PatrolScrubDuration = 24; /* unit is hour */ + + /* Disable below UPDs because those features should be implemented by coreboot */ + mupd->FspmConfig.LockChipset = 0; + mupd->FspmConfig.ProcessorMsrLockControl = 0; + /* Don't set and signal MSR_BIOS_DONE in FSP since it should be done by coreboot */ + mupd->FspmConfig.DfxDisableBiosDone = 1; + + u32 cpu_id = cpu_get_cpuid(); + if (cpu_id == (u32)CPUID_SAPPHIRERAPIDS_SP_D) { + printk(BIOS_DEBUG, "CPU is D stepping, setting package C state to C0/C1\n"); + mupd->FspmConfig.CpuPmPackageCState = 0; + } + /* Set some common UPDs from VPD, mainboard can still override them if needed */ + if (CONFIG(VPD)) + config_upd_from_vpd(mupd); + initialize_iio_upd(mupd); + mainboard_memory_init_params(mupd); +} + +static uint8_t get_error_correction_type(const uint8_t RasModesEnabled) +{ + switch (RasModesEnabled) { + case CH_INDEPENDENT: + return MEMORY_ARRAY_ECC_SINGLE_BIT; + case FULL_MIRROR_1LM: + case PARTIAL_MIRROR_1LM: + case FULL_MIRROR_2LM: + case PARTIAL_MIRROR_2LM: + return MEMORY_ARRAY_ECC_MULTI_BIT; + case RK_SPARE: + return MEMORY_ARRAY_ECC_SINGLE_BIT; + case CH_LOCKSTEP: + return MEMORY_ARRAY_ECC_SINGLE_BIT; + default: + return MEMORY_ARRAY_ECC_MULTI_BIT; + } +} + +/* Save the DIMM information for SMBIOS table 17 */ +void save_dimm_info(void) +{ + struct dimm_info *dest_dimm; + struct memory_info *mem_info; + const struct SystemMemoryMapHob *hob; + MEMMAP_DIMM_DEVICE_INFO_STRUCT src_dimm; + int dimm_max, dimm_num = 0; + int index = 0; + uint8_t mem_dev_type; + uint16_t data_width; + uint32_t vdd_voltage; + + hob = get_system_memory_map(); + assert(hob != NULL); + + /* + * Allocate CBMEM area for DIMM information used to populate SMBIOS + * table 17 + */ + mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); + if (mem_info == NULL) { + printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n"); + return; + } + memset(mem_info, 0, sizeof(*mem_info)); + /* According to EDS doc#611488, it's 4 TB per processor. */ + mem_info->max_capacity_mib = 4 * MiB * CONFIG_MAX_SOCKET; + mem_info->number_of_devices = CONFIG_DIMM_MAX; + mem_info->ecc_type = get_error_correction_type(hob->RasModesEnabled); + dimm_max = ARRAY_SIZE(mem_info->dimm); + vdd_voltage = get_ddr_millivolt(hob->DdrVoltage); + for (int soc = 0; soc < CONFIG_MAX_SOCKET; soc++) { + for (int ch = 0; ch < MAX_CH; ch++) { + for (int dimm = 0; dimm < MAX_DIMM; dimm++) { + if (index >= dimm_max) { + printk(BIOS_WARNING, "Too many DIMMs info for %s.\n", + __func__); + return; + } + + src_dimm = hob->Socket[soc].ChannelInfo[ch].DimmInfo[dimm]; + if (src_dimm.Present) { + dest_dimm = &mem_info->dimm[index]; + index++; + } else if (mainboard_dimm_slot_exists(soc, ch, dimm)) { + dest_dimm = &mem_info->dimm[index]; + index++; + /* Save DIMM Locator information for SMBIOS Type 17 */ + dest_dimm->dimm_size = 0; + dest_dimm->soc_num = soc; + dest_dimm->channel_num = ch; + dest_dimm->dimm_num = dimm; + continue; + } else { + /* Ignore DIMM that isn't present and doesn't exist on + the board. */ + continue; + } + dest_dimm->max_speed_mts = + get_max_memory_speed(src_dimm.commonTck); + dest_dimm->configured_speed_mts = hob->memFreq; + dest_dimm->soc_num = soc; + + if (hob->DramType == SPD_TYPE_DDR5) { + /* hard-coded memory device type as DDR5 */ + mem_dev_type = 0x22; + data_width = 64; + } else { + /* hard-coded memory device type as DDR4 */ + mem_dev_type = 0x1A; + data_width = 64; + } + dimm_info_fill( + dest_dimm, src_dimm.DimmSize << 6, mem_dev_type, + hob->memFreq, /* replaced by configured_speed_mts */ + src_dimm.NumRanks, + ch, /* for mainboard locator string override */ + dimm, /* for mainboard locator string override */ + (const char *)&src_dimm.PartNumber[0], + sizeof(src_dimm.PartNumber), + (const uint8_t *)&src_dimm.serialNumber[0], data_width, + vdd_voltage, true, /* hard-coded as ECC supported */ + src_dimm.VendorID, src_dimm.actKeyByte2, 0); + dimm_num++; + } + } + } + + mem_info->dimm_cnt = index; /* Number of DIMM slots found */ + printk(BIOS_DEBUG, "%d Installed DIMMs found\n", dimm_num); +} + +void fsp_check_for_error(void) +{ + check_fsp_error(); +} diff --git a/src/soc/intel/xeon_sp/spr/soc_util.c b/src/soc/intel/xeon_sp/spr/soc_util.c new file mode 100644 index 0000000000..053b3ebeca --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/soc_util.c @@ -0,0 +1,177 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <assert.h> +#include <device/device.h> +#include <device/pci.h> +#include <hob_cxlnode.h> +#include <intelblocks/cpulib.h> +#include <soc/cpu.h> +#include <soc/msr.h> +#include <soc/numa.h> +#include <soc/pci_devs.h> +#include <soc/soc_util.h> +#include <soc/util.h> +#include <stdlib.h> +#include <string.h> + +const EWL_PRIVATE_DATA *get_ewl_hob(void) +{ + size_t hob_size; + static const EWL_PRIVATE_DATA *hob; + const uint8_t ewl_id_hob_guid[16] = FSP_HOB_EWLID_GUID; + + if (hob != NULL) + return hob; + + hob = fsp_find_extension_hob_by_guid(ewl_id_hob_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + return hob; +} + +const SYSTEM_INFO_VAR *get_system_info_hob(void) +{ + size_t hob_size; + static const SYSTEM_INFO_VAR *hob; + const uint8_t system_info_hob_guid[16] = FSP_HOB_SYSTEMINFO_GUID; + + if (hob != NULL) + return hob; + + hob = fsp_find_extension_hob_by_guid(system_info_hob_guid, &hob_size); + assert(hob != NULL && hob_size != 0); + return hob; +} + +const struct SystemMemoryMapHob *get_system_memory_map(void) +{ + size_t hob_size; + const uint8_t mem_hob_guid[16] = FSP_SYSTEM_MEMORYMAP_HOB_GUID; + const struct SystemMemoryMapHob **memmap_addr; + + memmap_addr = (const struct SystemMemoryMapHob **)fsp_find_extension_hob_by_guid( + mem_hob_guid, &hob_size); + /* hob_size is the size of the 8-byte address not the hob data */ + assert(memmap_addr != NULL && hob_size != 0); + /* assert the pointer to the hob is not NULL */ + assert(*memmap_addr != NULL); + + return *memmap_addr; +} + +const struct SystemMemoryMapElement *get_system_memory_map_elment(uint8_t *num) +{ + const struct SystemMemoryMapHob *hob = get_system_memory_map(); + if (!hob) + return NULL; + + *num = hob->numberEntries; + return hob->Element; +} + +bool is_iio_stack_res(const STACK_RES *res) +{ + return res->Personality == TYPE_UBOX_IIO || res->Personality == TYPE_DINO; +} + +/* + * Given a stack resource, figure out whether the corresponding stack has + * CXL device. + * It goes through pds (proximity domains) structure to see if there is any + * generic initiator has device with bus # falls between bus base and + * bus limit. + */ +bool is_iio_cxl_stack_res(const STACK_RES *res) +{ + for (uint8_t i = 0; i < pds.num_pds; i++) { + if (pds.pds[i].pd_type == PD_TYPE_PROCESSOR) + continue; + + uint32_t bus = pds.pds[i].device_handle >> 20; + if (bus >= res->BusBase && bus <= res->BusLimit) + return true; + } + + return false; +} + +const CXL_NODE_SOCKET *get_cxl_node(void) +{ + size_t hob_size; + static const CXL_NODE_SOCKET *hob; + static bool hob_check = 0; + const uint8_t fsp_hob_cxl_node_socket_guid[16] = FSP_HOB_CXLNODE_GUID; + + if (hob_check == 1) + return hob; + + hob = fsp_find_extension_hob_by_guid(fsp_hob_cxl_node_socket_guid, &hob_size); + hob_check = 1; + if (hob == NULL || hob_size == 0) + printk(BIOS_DEBUG, + "FSP_HOB_CXLNODE_GUID not found: CXL may not be installed\n"); + return hob; +} + +uint8_t get_cxl_node_count(void) +{ + const CXL_NODE_SOCKET *hob = get_cxl_node(); + uint8_t count = 0; + + if (hob != NULL) { + for (uint8_t skt_id = 0; skt_id < MAX_SOCKET; skt_id++) + count += hob[skt_id].CxlNodeCount; + } + + return count; +} + +uint32_t get_socket_stack_busno(uint32_t socket, uint32_t stack) +{ + const IIO_UDS *hob = get_iio_uds(); + + assert(socket < hob->SystemStatus.numCpus && stack < MAX_LOGIC_IIO_STACK); + + return hob->PlatformData.IIO_resource[socket].StackRes[stack].BusBase; +} + +uint32_t get_ubox_busno(uint32_t socket, uint8_t offset) +{ + const IIO_UDS *hob = get_iio_uds(); + + assert(socket < hob->SystemStatus.numCpus); + for (int stack = 0; stack < MAX_LOGIC_IIO_STACK; ++stack) { + if (hob->PlatformData.IIO_resource[socket].StackRes[stack].Personality + == TYPE_UBOX) + return (hob->PlatformData.IIO_resource[socket].StackRes[stack].BusBase + + offset); + } + die("Unable to locate UBOX BUS NO"); +} + +uint32_t get_socket_ubox_busno(uint32_t socket) +{ + return get_ubox_busno(socket, UNCORE_BUS_1); +} + +/* mainboard can override this function for their own handling, such as write a BMC SEL. */ +void __weak mainboard_fsp_error_handle(void) +{ + die("ERROR: FSP reported an error(s) after running!"); +} + +void check_fsp_error(void) +{ + bool fsp_found_error = fsp_find_error_info(); + + if (fsp_found_error) + mainboard_fsp_error_handle(); +} + +void bios_done_msr(void *unused) +{ + msr_t msr = rdmsr(MSR_BIOS_DONE); + if (!(msr.lo & XEON_SP_ENABLE_IA_UNTRUSTED)) { /* if already locked skip update */ + msr.lo |= XEON_SP_ENABLE_IA_UNTRUSTED; + wrmsr(MSR_BIOS_DONE, msr); + } +} diff --git a/src/soc/intel/xeon_sp/spr/upd_display.c b/src/soc/intel/xeon_sp/spr/upd_display.c new file mode 100644 index 0000000000..078624db15 --- /dev/null +++ b/src/soc/intel/xeon_sp/spr/upd_display.c @@ -0,0 +1,139 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <console/console.h> +#include <fsp/util.h> +#include <lib.h> + +#define DUMP_UPD(old, new, field) \ + fsp_display_upd_value(#field, sizeof(old->field), old->field, new->field) + +static void soc_display_fspm_upd_iio(const FSPM_UPD *mupd) +{ + int port, socket; + + UPD_IIO_PCIE_PORT_CONFIG *PciePortConfig = + (UPD_IIO_PCIE_PORT_CONFIG *)mupd->FspmConfig.IioPcieConfigTablePtr; + + printk(BIOS_SPEW, "UPD values for IIO:\n"); + for (socket = 0; socket < mupd->FspmConfig.IioPcieConfigTableNumber; socket++) { + printk(BIOS_SPEW, "Socket: %d\n", socket); + for (port = 0; port < MAX_IIO_PORTS_PER_SOCKET; port++) { + printk(BIOS_SPEW, "port: %d\n", port); + + printk(BIOS_SPEW, "\tSLOTEIP: 0x%x\n", + PciePortConfig[socket].SLOTEIP[port]); + printk(BIOS_SPEW, "\tSLOTHPCAP: 0x%x\n", + PciePortConfig[socket].SLOTHPCAP[port]); + printk(BIOS_SPEW, "\tSLOTHPSUP: 0x%x\n", + PciePortConfig[socket].SLOTHPSUP[port]); + printk(BIOS_SPEW, "\tSLOTPIP: 0x%x\n", + PciePortConfig[socket].SLOTPIP[port]); + printk(BIOS_SPEW, "\tSLOTAIP: 0x%x\n", + PciePortConfig[socket].SLOTAIP[port]); + printk(BIOS_SPEW, "\tSLOTMRLSP: 0x%x\n", + PciePortConfig[socket].SLOTMRLSP[port]); + printk(BIOS_SPEW, "\tSLOTPCP: 0x%x\n", + PciePortConfig[socket].SLOTPCP[port]); + printk(BIOS_SPEW, "\tSLOTABP: 0x%x\n", + PciePortConfig[socket].SLOTABP[port]); + printk(BIOS_SPEW, "\tSLOTIMP: 0x%x\n", + PciePortConfig[socket].SLOTIMP[port]); + printk(BIOS_SPEW, "\tSLOTSPLS: 0x%x\n", + PciePortConfig[socket].SLOTSPLS[port]); + printk(BIOS_SPEW, "\tSLOTSPLV: 0x%x\n", + PciePortConfig[socket].SLOTSPLV[port]); + printk(BIOS_SPEW, "\tSLOTPSP: 0x%x\n", + PciePortConfig[socket].SLOTPSP[port]); + printk(BIOS_SPEW, "\tVppEnabled: 0x%x\n", + PciePortConfig[socket].VppEnabled[port]); + printk(BIOS_SPEW, "\tVppPort: 0x%x\n", + PciePortConfig[socket].VppPort[port]); + printk(BIOS_SPEW, "\tVppAddress: 0x%x\n", + PciePortConfig[socket].VppAddress[port]); + printk(BIOS_SPEW, "\tMuxAddress: 0x%x\n", + PciePortConfig[socket].MuxAddress[port]); + printk(BIOS_SPEW, "\tChannelID: 0x%x\n", + PciePortConfig[socket].ChannelID[port]); + printk(BIOS_SPEW, "\tPciePortEnable: 0x%x\n", + PciePortConfig[socket].PciePortEnable[port]); + printk(BIOS_SPEW, "\tPEXPHIDE: 0x%x\n", + PciePortConfig[socket].PEXPHIDE[port]); + printk(BIOS_SPEW, "\tHidePEXPMenu: 0x%x\n", + PciePortConfig[socket].HidePEXPMenu[port]); + printk(BIOS_SPEW, "\tPciePortOwnership: 0x%x\n", + PciePortConfig[socket].PciePortOwnership[port]); + printk(BIOS_SPEW, "\tRetimerConnectCount: 0x%x\n", + PciePortConfig[socket].RetimerConnectCount[port]); + printk(BIOS_SPEW, "\tPcieHotPlugOnPort: 0x%x\n", + PciePortConfig[socket].PcieHotPlugOnPort[port]); + printk(BIOS_SPEW, "\tVMDPortEnable: 0x%x\n", + PciePortConfig[socket].VMDPortEnable[port]); + printk(BIOS_SPEW, "\tPcieMaxPayload: 0x%x\n", + PciePortConfig[socket].PcieMaxPayload[port]); + printk(BIOS_SPEW, "\tPciePortLinkSpeed: 0x%x\n", + PciePortConfig[socket].PciePortLinkSpeed[port]); + printk(BIOS_SPEW, "\tDfxDnTxPresetGen3: 0x%x\n", + PciePortConfig[socket].DfxDnTxPresetGen3[port]); + } + + for (port = 0; port < MAX_VMD_STACKS_PER_SOCKET; port++) { + printk(BIOS_SPEW, "port: %d\n", port); + printk(BIOS_SPEW, "\tVMDEnabled: 0x%x\n", + PciePortConfig[socket].VMDEnabled[port]); + printk(BIOS_SPEW, "\tVMDHotPlugEnable: 0x%x\n", + PciePortConfig[socket].VMDHotPlugEnable[port]); + } + printk(BIOS_SPEW, "ConfigIOU[0]: 0x%x\n", PciePortConfig[socket].ConfigIOU[0]); + printk(BIOS_SPEW, "ConfigIOU[1]: 0x%x\n", PciePortConfig[socket].ConfigIOU[1]); + printk(BIOS_SPEW, "ConfigIOU[2]: 0x%x\n", PciePortConfig[socket].ConfigIOU[2]); + printk(BIOS_SPEW, "ConfigIOU[3]: 0x%x\n", PciePortConfig[socket].ConfigIOU[3]); + printk(BIOS_SPEW, "ConfigIOU[4]: 0x%x\n", PciePortConfig[socket].ConfigIOU[4]); + printk(BIOS_SPEW, "PcieGlobalAspm: 0x%x\n", + PciePortConfig[socket].PcieGlobalAspm); + printk(BIOS_SPEW, "PcieMaxReadRequestSize: 0x%x\n", + PciePortConfig[socket].PcieMaxReadRequestSize); + } + + UINT8 *DeEmphasisConfig = (UINT8 *)mupd->FspmConfig.DeEmphasisPtr; + for (port = 0; port < mupd->FspmConfig.DeEmphasisNumber; port++) { + printk(BIOS_SPEW, "port: %d, DeEmphasisConfig: 0x%x\n", port, + DeEmphasisConfig[port]); + } +} + +/* Display the UPD parameters for MemoryInit */ +void soc_display_fspm_upd_params(const FSPM_UPD *fspm_old_upd, const FSPM_UPD *fspm_new_upd) +{ + const FSP_M_CONFIG *new; + const FSP_M_CONFIG *old; + + old = &fspm_old_upd->FspmConfig; + new = &fspm_new_upd->FspmConfig; + + printk(BIOS_DEBUG, "UPD values for MemoryInit:\n"); + DUMP_UPD(old, new, DebugPrintLevel); + DUMP_UPD(old, new, DfxCxlHeaderBypass); + DUMP_UPD(old, new, DfxCxlSecLvl); + + printk(BIOS_DEBUG, " Dump of original MemoryInit UPD:\n"); + hexdump(fspm_old_upd, sizeof(*fspm_old_upd)); + + printk(BIOS_DEBUG, " Dump of updated MemoryInit UPD:\n"); + hexdump(fspm_new_upd, sizeof(*fspm_new_upd)); + if (CONFIG(DISPLAY_UPD_IIO_DATA)) + soc_display_fspm_upd_iio(fspm_new_upd); +} + +/* Display the UPD parameters for SiliconInit */ +void soc_display_fsps_upd_params(const FSPS_UPD *fsps_old_upd, const FSPS_UPD *fsps_new_upd) +{ + const FSP_S_CONFIG *new; + const FSP_S_CONFIG *old; + + old = &fsps_old_upd->FspsConfig; + new = &fsps_new_upd->FspsConfig; + + printk(BIOS_DEBUG, "UPD values for SiliconInit:\n"); + + hexdump(fsps_new_upd, sizeof(*fsps_new_upd)); +} |