Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
| 2 | |
| 3 | #include <arch/romstage.h> |
| 4 | #include <cbmem.h> |
| 5 | #include <console/console.h> |
| 6 | #include <fsp/util.h> |
| 7 | #include <intelblocks/cfg.h> |
| 8 | #include <intelblocks/cse.h> |
| 9 | #include <intelblocks/pmclib.h> |
| 10 | #include <intelblocks/smbus.h> |
Subrata Banik | 2bce51e | 2022-09-08 13:29:22 -0700 | [diff] [blame] | 11 | #include <intelblocks/thermal.h> |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 12 | #include <memory_info.h> |
| 13 | #include <soc/intel/common/smbios.h> |
| 14 | #include <soc/iomap.h> |
| 15 | #include <soc/pm.h> |
| 16 | #include <soc/romstage.h> |
| 17 | #include <soc/soc_chip.h> |
Dinesh Gehlot | e29dcdc | 2022-11-30 09:28:54 +0000 | [diff] [blame] | 18 | #include <timestamp.h> |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 19 | #include <string.h> |
| 20 | |
| 21 | #define FSP_SMBIOS_MEMORY_INFO_GUID \ |
| 22 | { \ |
| 23 | 0xd4, 0x71, 0x20, 0x9b, 0x54, 0xb0, 0x0c, 0x4e, \ |
| 24 | 0x8d, 0x09, 0x11, 0xcf, 0x8b, 0x9f, 0x03, 0x23 \ |
| 25 | } |
| 26 | |
| 27 | /* Save the DIMM information for SMBIOS table 17 */ |
| 28 | static void save_dimm_info(void) |
| 29 | { |
| 30 | int node, channel, dimm, dimm_max, index; |
| 31 | size_t hob_size; |
| 32 | const CONTROLLER_INFO *ctrlr_info; |
| 33 | const CHANNEL_INFO *channel_info; |
| 34 | const DIMM_INFO *src_dimm; |
| 35 | struct dimm_info *dest_dimm; |
| 36 | struct memory_info *mem_info; |
| 37 | const MEMORY_INFO_DATA_HOB *meminfo_hob; |
| 38 | const uint8_t smbios_memory_info_guid[sizeof(EFI_GUID)] = FSP_SMBIOS_MEMORY_INFO_GUID; |
| 39 | const uint8_t *serial_num; |
| 40 | const char *dram_part_num = NULL; |
| 41 | size_t dram_part_num_len = 0; |
| 42 | |
| 43 | /* Locate the memory info HOB, presence validated by raminit */ |
| 44 | meminfo_hob = fsp_find_extension_hob_by_guid( |
| 45 | smbios_memory_info_guid, |
| 46 | &hob_size); |
Elyes Haouas | 6a8029c | 2022-09-13 10:16:01 +0200 | [diff] [blame] | 47 | if (!meminfo_hob || hob_size == 0) { |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 48 | printk(BIOS_ERR, "SMBIOS MEMORY_INFO_DATA_HOB not found\n"); |
| 49 | return; |
| 50 | } |
| 51 | |
| 52 | /* |
| 53 | * Allocate CBMEM area for DIMM information used to populate SMBIOS |
| 54 | * table 17 |
| 55 | */ |
| 56 | mem_info = cbmem_add(CBMEM_ID_MEMINFO, sizeof(*mem_info)); |
Elyes Haouas | 6a8029c | 2022-09-13 10:16:01 +0200 | [diff] [blame] | 57 | if (!mem_info) { |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 58 | printk(BIOS_ERR, "CBMEM entry for DIMM info missing\n"); |
| 59 | return; |
| 60 | } |
| 61 | memset(mem_info, 0, sizeof(*mem_info)); |
| 62 | |
| 63 | /* Allow mainboard to override DRAM part number. */ |
| 64 | dram_part_num = mainboard_get_dram_part_num(); |
| 65 | if (dram_part_num) |
| 66 | dram_part_num_len = strlen(dram_part_num); |
| 67 | |
| 68 | /* Save available DIMM information */ |
| 69 | index = 0; |
| 70 | dimm_max = ARRAY_SIZE(mem_info->dimm); |
| 71 | for (node = 0; node < MAX_NODE; node++) { |
| 72 | ctrlr_info = &meminfo_hob->Controller[node]; |
| 73 | for (channel = 0; channel < MAX_CH && index < dimm_max; channel++) { |
| 74 | channel_info = &ctrlr_info->ChannelInfo[channel]; |
| 75 | if (channel_info->Status != CHANNEL_PRESENT) |
| 76 | continue; |
| 77 | |
| 78 | for (dimm = 0; dimm < MAX_DIMM && index < dimm_max; dimm++) { |
| 79 | src_dimm = &channel_info->DimmInfo[dimm]; |
| 80 | dest_dimm = &mem_info->dimm[index]; |
| 81 | if (src_dimm->Status != DIMM_PRESENT) |
| 82 | continue; |
| 83 | |
| 84 | /* If there is no DRAM part number overridden by |
| 85 | * mainboard then use original one. */ |
| 86 | if (!dram_part_num) { |
| 87 | dram_part_num_len = sizeof(src_dimm->ModulePartNum); |
| 88 | dram_part_num = (const char *) |
| 89 | &src_dimm->ModulePartNum[0]; |
| 90 | } |
| 91 | |
| 92 | uint8_t memProfNum = meminfo_hob->MemoryProfile; |
| 93 | serial_num = src_dimm->SpdSave + SPD_SAVE_OFFSET_SERIAL; |
| 94 | |
| 95 | /* Populate the DIMM information */ |
| 96 | dimm_info_fill(dest_dimm, |
| 97 | src_dimm->DimmCapacity, |
| 98 | meminfo_hob->MemoryType, |
| 99 | meminfo_hob->ConfiguredMemoryClockSpeed, |
| 100 | src_dimm->RankInDimm, |
| 101 | channel_info->ChannelId, |
| 102 | src_dimm->DimmId, |
| 103 | dram_part_num, |
| 104 | dram_part_num_len, |
| 105 | serial_num, |
| 106 | meminfo_hob->DataWidth, |
| 107 | meminfo_hob->VddVoltage[memProfNum], |
| 108 | meminfo_hob->EccSupport, |
| 109 | src_dimm->MfgId, |
David Milosevic | 6be82a4 | 2022-10-18 19:17:19 +0200 | [diff] [blame] | 110 | src_dimm->SpdModuleType, |
Eric Lai | b15946d | 2023-06-13 10:21:58 +0800 | [diff] [blame^] | 111 | node, |
| 112 | meminfo_hob->MaximumMemoryClockSpeed); |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 113 | index++; |
| 114 | } |
| 115 | } |
| 116 | } |
| 117 | mem_info->dimm_cnt = index; |
Subrata Banik | ecb4a24 | 2023-03-16 18:25:45 +0530 | [diff] [blame] | 118 | if (mem_info->dimm_cnt == 0) |
| 119 | printk(BIOS_ERR, "No DIMMs found\n"); |
| 120 | else |
| 121 | printk(BIOS_DEBUG, "%d DIMMs found\n", mem_info->dimm_cnt); |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 122 | } |
| 123 | |
| 124 | void mainboard_romstage_entry(void) |
| 125 | { |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 126 | struct chipset_power_state *ps = pmc_get_power_state(); |
Subrata Banik | d4cc902 | 2023-01-16 13:52:40 +0530 | [diff] [blame] | 127 | bool s3wake = pmc_fill_power_state(ps) == ACPI_S3; |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 128 | |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 129 | /* Initialize HECI interface */ |
| 130 | cse_init(HECI1_BASE_ADDRESS); |
| 131 | |
Subrata Banik | 5ff0118 | 2023-04-20 11:08:17 +0530 | [diff] [blame] | 132 | if (!s3wake && CONFIG(SOC_INTEL_CSE_LITE_SKU)) |
Sridhar Siricilla | 1e638ba | 2022-12-08 11:40:02 +0530 | [diff] [blame] | 133 | cse_fw_sync(); |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 134 | |
Bora Guvendik | 34c37bb | 2023-03-13 14:27:30 -0700 | [diff] [blame] | 135 | /* Update coreboot timestamp table with CSE timestamps */ |
| 136 | if (CONFIG(SOC_INTEL_CSE_PRE_CPU_RESET_TELEMETRY)) |
| 137 | cse_get_telemetry_data(); |
| 138 | |
Subrata Banik | d4cc902 | 2023-01-16 13:52:40 +0530 | [diff] [blame] | 139 | /* Program MCHBAR, DMIBAR, GDXBAR and EDRAMBAR */ |
| 140 | systemagent_early_init(); |
| 141 | /* Program SMBus base address and enable it */ |
| 142 | smbus_common_init(); |
| 143 | |
Subrata Banik | 2bce51e | 2022-09-08 13:29:22 -0700 | [diff] [blame] | 144 | /* |
| 145 | * Set low maximum temp threshold value used for dynamic thermal sensor |
| 146 | * shutdown consideration. |
| 147 | * |
| 148 | * If Dynamic Thermal Shutdown is enabled then PMC logic shuts down the |
| 149 | * thermal sensor when CPU is in a C-state and LTT >= DTS Temp. |
| 150 | */ |
| 151 | pch_thermal_configuration(); |
Ravi Sarawadi | 8069b5d | 2022-04-10 23:36:52 -0700 | [diff] [blame] | 152 | fsp_memory_init(s3wake); |
| 153 | pmc_set_disb(); |
| 154 | if (!s3wake) |
| 155 | save_dimm_info(); |
| 156 | } |