blob: f846055fc2f041f676b228f32e989e9ee6ee818c [file] [log] [blame]
Jonathan Zhang826523b2020-04-09 10:42:19 -07001/* SPDX-License-Identifier: GPL-2.0-only */
2
Johnny Lin9da02792020-08-18 19:09:10 +08003#include <assert.h>
Elyes Haouas9efe34a2022-10-10 11:27:56 +02004#include <commonlib/bsd/helpers.h>
Johnny Lin407b35a2020-05-12 10:05:27 +08005#include <console/console.h>
Elyes Haouas9efe34a2022-10-10 11:27:56 +02006#include <cpu/cpu.h>
Patrick Rudolph7a593ab2024-01-25 15:15:00 +01007#include <cpu/x86/smm.h>
Elyes Haouas9efe34a2022-10-10 11:27:56 +02008#include <cpxsp_dl_gpio.h>
9#include <device/device.h>
10#include <device/pci_def.h>
11#include <device/pci_ops.h>
Johnny Lin407b35a2020-05-12 10:05:27 +080012#include <drivers/ipmi/ipmi_ops.h>
13#include <drivers/ocp/dmi/ocp_dmi.h>
Arthur Heymans8c6ee912021-02-02 19:16:08 +010014#include <drivers/vpd/vpd.h>
Morgan Jang98621382020-06-11 16:32:16 +080015#include <hob_iiouds.h>
Johnny Lin9da02792020-08-18 19:09:10 +080016#include <hob_memmap.h>
Elyes Haouas9efe34a2022-10-10 11:27:56 +020017#include <security/intel/txt/txt.h>
18#include <smbios.h>
19#include <soc/ramstage.h>
Patrick Rudolph7a593ab2024-01-25 15:15:00 +010020#include <soc/smmrelocate.h>
Elyes Haouas9efe34a2022-10-10 11:27:56 +020021#include <soc/soc_util.h>
22#include <soc/util.h>
23#include <stdio.h>
24#include <string.h>
25#include <types.h>
Jonathan Zhang826523b2020-04-09 10:42:19 -070026
Johnny Lin407b35a2020-05-12 10:05:27 +080027#include "ipmi.h"
Arthur Heymans8c6ee912021-02-02 19:16:08 +010028#include "vpd.h"
Johnny Lin407b35a2020-05-12 10:05:27 +080029
Johnny Lin5e8709f2020-06-11 15:25:37 +080030#define SLOT_ID_LEN 2
31
Johnny Lin407b35a2020-05-12 10:05:27 +080032extern struct fru_info_str fru_strings;
Johnny Lin5e8709f2020-06-11 15:25:37 +080033static char slot_id_str[SLOT_ID_LEN];
34
35/* Override SMBIOS 2 Location In Chassis from BMC */
36const char *smbios_mainboard_location_in_chassis(void)
37{
38 uint8_t slot_id = 0;
39
40 if (ipmi_get_slot_id(&slot_id) != CB_SUCCESS) {
41 printk(BIOS_ERR, "IPMI get slot_id failed\n");
42 return "";
43 }
44 /* Sanity check, slot_id can only be 1~4 since there are 4 slots in YV3 */
45 if (slot_id < PCIE_CONFIG_A || slot_id > PCIE_CONFIG_D) {
46 printk(BIOS_ERR, "slot_id %d is not between 1~4\n", slot_id);
47 return "";
48 }
49 snprintf(slot_id_str, SLOT_ID_LEN, "%d", slot_id);
50 return slot_id_str;
51}
Johnny Lin407b35a2020-05-12 10:05:27 +080052
Tim Chue82aa222020-12-21 23:33:18 -080053/* Override SMBIOS type 2 Feature Flags */
54u8 smbios_mainboard_feature_flags(void)
55{
56 return SMBIOS_FEATURE_FLAGS_HOSTING_BOARD | SMBIOS_FEATURE_FLAGS_REPLACEABLE;
57}
58
Tim Chube34afa2020-11-13 03:04:54 -080059/*
60 * Override SMBIOS type 4 cpu voltage.
61 * BIT7 will set to 1 after value return. If BIT7 is set to 1, the remaining seven
62 * bits of this field are set to contain the processor's current voltage times 10.
63 */
64unsigned int smbios_cpu_get_voltage(void)
65{
66 /* This will return 1.6V which is expected value for Delta Lake
67 10h = (1.6 * 10) = 16 */
68 return 0x10;
69}
70
Morgan Jang98621382020-06-11 16:32:16 +080071/* System Slot Socket, Stack, Type and Data bus width Information */
72typedef struct {
73 u8 stack;
74 u8 slot_type;
75 u8 slot_data_bus_width;
76 u8 dev_func;
77 const char *slot_designator;
78} slot_info;
79
JingleHsuWiwynn20fa59f2021-01-26 09:55:34 +080080/* Array index + 1 would be used as Slot ID */
Morgan Jang98621382020-06-11 16:32:16 +080081slot_info slotinfo[] = {
Jingle Hsu5b24c6d2020-10-07 16:02:51 +080082 {CSTACK, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0xE8, "SSD1_M2_Data_Drive"},
83 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x10, "SSD0_M2_Boot_Drive"},
84 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x18, "BB_OCP_NIC"},
Johnny Linc8ea2122021-03-10 11:15:53 +080085 {PSTACK2, SlotTypePciExpressGen3X16, SlotDataBusWidth16X, 0x00, "1OU_OCP_NIC"},
Jingle Hsu5b24c6d2020-10-07 16:02:51 +080086 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x00, "2OU_JD1_M2_0"},
87 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x08, "2OU_JD1_M2_1"},
Johnny Linc8ea2122021-03-10 11:15:53 +080088 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x08, "2OU_JD2_M2_2"},
89 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x00, "2OU_JD2_M2_3"},
Jingle Hsu5b24c6d2020-10-07 16:02:51 +080090 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x10, "2OU_JD3_M2_4"},
91 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x18, "2OU_JD3_M2_5"},
Johnny Linc8ea2122021-03-10 11:15:53 +080092 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x18, "1OU_JD1_M2_0"},
93 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x10, "1OU_JD1_M2_1"},
94 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x08, "1OU_JD2_M2_2"},
95 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x00, "1OU_JD2_M2_3"},
Morgan Jang98621382020-06-11 16:32:16 +080096};
97
Johnny Lin9da02792020-08-18 19:09:10 +080098#define SPD_REGVID_LEN 6
99/* A 4-digit long number plus a space */
100static void write_oem_word(uint16_t val, char *str)
101{
102 snprintf(str, SPD_REGVID_LEN, "%04x ", val);
103}
104
Johnny Lin407b35a2020-05-12 10:05:27 +0800105static void dl_oem_smbios_strings(struct device *dev, struct smbios_type11 *t)
106{
107 uint8_t pcie_config = 0;
Johnny Lin9da02792020-08-18 19:09:10 +0800108 const struct SystemMemoryMapHob *hob;
109 char spd_reg_vid[SPD_REGVID_LEN];
110 char empty[1] = "";
111 char *oem_str7 = empty;
Johnny Lin407b35a2020-05-12 10:05:27 +0800112
113 /* OEM string 1 to 6 */
114 ocp_oem_smbios_strings(dev, t);
115
Johnny Lin9da02792020-08-18 19:09:10 +0800116 /* OEM string 7 is the register vendor ID in SPD for each DIMM strung together */
117 hob = get_system_memory_map();
Elyes Haouas3de12532022-09-13 10:14:27 +0200118 assert(hob);
Johnny Lin9da02792020-08-18 19:09:10 +0800119 /* There are at most 6 channels and 2 DIMMs per channel, but Delta Lake has 6 DIMMs,
120 e.g. b300 0000 b300 0000 b300 0000 b300 0000 b300 0000 b300 0000 */
121 for (int ch = 0; ch < MAX_CH; ch++) {
122 for (int dimm = 0; dimm < MAX_IMC; dimm++) {
123 write_oem_word(hob->Socket[0].ChannelInfo[ch].DimmInfo[dimm].SPDRegVen,
124 spd_reg_vid);
125 oem_str7 = strconcat(oem_str7, spd_reg_vid);
126 }
127 }
128 t->count = smbios_add_oem_string(t->eos, oem_str7);
Johnny Lin407b35a2020-05-12 10:05:27 +0800129
130 /* Add OEM string 8 */
131 if (ipmi_get_pcie_config(&pcie_config) == CB_SUCCESS) {
132 switch (pcie_config) {
133 case PCIE_CONFIG_UNKNOWN:
134 t->count = smbios_add_oem_string(t->eos, "0x0: Unknown");
135 break;
136 case PCIE_CONFIG_A:
137 t->count = smbios_add_oem_string(t->eos, "0x1: YV3 Config-A");
138 break;
139 case PCIE_CONFIG_B:
140 t->count = smbios_add_oem_string(t->eos, "0x2: YV3 Config-B");
141 break;
142 case PCIE_CONFIG_C:
143 t->count = smbios_add_oem_string(t->eos, "0x3: YV3 Config-C");
144 break;
145 case PCIE_CONFIG_D:
146 t->count = smbios_add_oem_string(t->eos, "0x4: YV3 Config-D");
147 break;
148 default:
149 t->count = smbios_add_oem_string(t->eos, "Check BMC return data");
150 }
151 } else {
152 printk(BIOS_ERR, "Failed to get IPMI PCIe config\n");
153 }
154}
155
Tim Chu39ea2232020-11-23 21:24:20 -0800156static const struct port_information smbios_type8_info[] = {
157 {
158 .internal_reference_designator = "JCN18 - CPU MIPI60",
159 .internal_connector_type = CONN_OTHER,
160 .external_reference_designator = "",
161 .external_connector_type = CONN_NONE,
162 .port_type = TYPE_OTHER_PORT
163 },
164 {
165 .internal_reference_designator = "JCN32 - TPM_CONN",
166 .internal_connector_type = CONN_OTHER,
167 .external_reference_designator = "",
168 .external_connector_type = CONN_NONE,
169 .port_type = TYPE_OTHER_PORT
170 },
171 {
172 .internal_reference_designator = "JCN7 - USB type C",
173 .internal_connector_type = CONN_USB_TYPE_C,
174 .external_reference_designator = "",
175 .external_connector_type = CONN_NONE,
176 .port_type = TYPE_USB
177 },
178};
179
Morgan Jang98621382020-06-11 16:32:16 +0800180static int create_smbios_type9(int *handle, unsigned long *current)
181{
182 int index;
183 int length = 0;
184 uint8_t slot_length;
185 uint8_t sec_bus;
186 uint8_t slot_usage;
187 uint8_t pcie_config = 0;
Morgan Jang98621382020-06-11 16:32:16 +0800188 uint32_t vendor_device_id;
Maxim Polyakov91a45122021-01-14 01:37:26 +0300189 uint8_t stack_busnos[MAX_IIO_STACK];
Johnny Lincfe15a22021-10-05 08:33:08 +0800190 pci_devfn_t pci_dev_slot, pci_dev = 0;
Morgan Jang98621382020-06-11 16:32:16 +0800191 unsigned int cap;
192 uint16_t sltcap;
193
194 if (ipmi_get_pcie_config(&pcie_config) != CB_SUCCESS)
195 printk(BIOS_ERR, "Failed to get IPMI PCIe config\n");
196
Maxim Polyakov91a45122021-01-14 01:37:26 +0300197 for (index = 0; index < ARRAY_SIZE(stack_busnos); index++)
198 stack_busnos[index] = get_stack_busno(index);
Morgan Jang98621382020-06-11 16:32:16 +0800199
200 for (index = 0; index < ARRAY_SIZE(slotinfo); index++) {
Johnny Lincfe15a22021-10-05 08:33:08 +0800201 uint8_t characteristics_1 = 0;
202 uint8_t characteristics_2 = 0;
203
Morgan Jang98621382020-06-11 16:32:16 +0800204 if (pcie_config == PCIE_CONFIG_A) {
Jingle Hsu5b24c6d2020-10-07 16:02:51 +0800205 if (index == 0 || index == 1 || index == 2)
Morgan Jang98621382020-06-11 16:32:16 +0800206 printk(BIOS_INFO, "Find Config-A slot: %s\n",
207 slotinfo[index].slot_designator);
208 else
209 continue;
210 }
211 if (pcie_config == PCIE_CONFIG_B) {
Johnny Linc8ea2122021-03-10 11:15:53 +0800212 switch (index) {
213 case 0 ... 2:
214 case 10 ... 13:
Morgan Jang98621382020-06-11 16:32:16 +0800215 printk(BIOS_INFO, "Find Config-B slot: %s\n",
216 slotinfo[index].slot_designator);
Johnny Linc8ea2122021-03-10 11:15:53 +0800217 break;
218 default:
Morgan Jang98621382020-06-11 16:32:16 +0800219 continue;
Johnny Linc8ea2122021-03-10 11:15:53 +0800220 }
Morgan Jang98621382020-06-11 16:32:16 +0800221 }
222 if (pcie_config == PCIE_CONFIG_C) {
Johnny Linc8ea2122021-03-10 11:15:53 +0800223 switch (index) {
224 case 0 ... 1:
225 case 3 ... 9:
Morgan Jang98621382020-06-11 16:32:16 +0800226 printk(BIOS_INFO, "Find Config-C slot: %s\n",
227 slotinfo[index].slot_designator);
Johnny Linc8ea2122021-03-10 11:15:53 +0800228 break;
229 default:
Morgan Jang98621382020-06-11 16:32:16 +0800230 continue;
Johnny Linc8ea2122021-03-10 11:15:53 +0800231 }
Morgan Jang98621382020-06-11 16:32:16 +0800232 }
233 if (pcie_config == PCIE_CONFIG_D) {
Johnny Linc8ea2122021-03-10 11:15:53 +0800234 if (index != 3)
Morgan Jang98621382020-06-11 16:32:16 +0800235 printk(BIOS_INFO, "Find Config-D slot: %s\n",
236 slotinfo[index].slot_designator);
237 else
238 continue;
239 }
240
241 if (slotinfo[index].slot_data_bus_width == SlotDataBusWidth16X)
242 slot_length = SlotLengthLong;
243 else
244 slot_length = SlotLengthShort;
245
Johnny Lincfe15a22021-10-05 08:33:08 +0800246 pci_dev_slot = PCI_DEV(stack_busnos[slotinfo[index].stack],
Morgan Jang98621382020-06-11 16:32:16 +0800247 slotinfo[index].dev_func >> 3, slotinfo[index].dev_func & 0x7);
Johnny Lincfe15a22021-10-05 08:33:08 +0800248 sec_bus = pci_s_read_config8(pci_dev_slot, PCI_SECONDARY_BUS);
Morgan Jang98621382020-06-11 16:32:16 +0800249
250 if (sec_bus == 0xFF) {
251 slot_usage = SlotUsageUnknown;
252 } else {
Johnny Lincfe15a22021-10-05 08:33:08 +0800253 /* Checking for downstream device availability */
Morgan Jang98621382020-06-11 16:32:16 +0800254 pci_dev = PCI_DEV(sec_bus, 0, 0);
255 vendor_device_id = pci_s_read_config32(pci_dev, 0);
256 if (vendor_device_id == 0xFFFFFFFF)
257 slot_usage = SlotUsageAvailable;
258 else
259 slot_usage = SlotUsageInUse;
260 }
261
262 characteristics_1 |= SMBIOS_SLOT_3P3V; // Provides33Volts
263 characteristics_2 |= SMBIOS_SLOT_PME; // PmeSiganalSupported
Johnny Lincfe15a22021-10-05 08:33:08 +0800264 /* Read IIO root port device CSR for slot capabilities */
265 cap = pci_s_find_capability(pci_dev_slot, PCI_CAP_ID_PCIE);
266 sltcap = pci_s_read_config16(pci_dev_slot, cap + PCI_EXP_SLTCAP);
Morgan Jang98621382020-06-11 16:32:16 +0800267 if (sltcap & PCI_EXP_SLTCAP_HPC)
268 characteristics_2 |= SMBIOS_SLOT_HOTPLUG;
269
JingleHsuWiwynn20fa59f2021-01-26 09:55:34 +0800270 const uint16_t slot_id = index + 1;
Johnny Lincfe15a22021-10-05 08:33:08 +0800271 /* According to SMBIOS spec, the BDF number should be the end
272 point on the slot, for now we keep using the root port's BDF to
273 be aligned with our UEFI reference BIOS. */
Morgan Jang98621382020-06-11 16:32:16 +0800274 length += smbios_write_type9(current, handle,
275 slotinfo[index].slot_designator,
276 slotinfo[index].slot_type,
277 slotinfo[index].slot_data_bus_width,
278 slot_usage,
279 slot_length,
JingleHsuWiwynn20fa59f2021-01-26 09:55:34 +0800280 slot_id,
Morgan Jang98621382020-06-11 16:32:16 +0800281 characteristics_1,
282 characteristics_2,
Felix Heldd4594032024-01-11 21:50:36 +0100283 0, /* segment group */
Morgan Jang98621382020-06-11 16:32:16 +0800284 stack_busnos[slotinfo[index].stack],
285 slotinfo[index].dev_func);
286 }
287
288 return length;
289}
290
291static int mainboard_smbios_data(struct device *dev, int *handle, unsigned long *current)
292{
293 int len = 0;
294
Tim Chu39ea2232020-11-23 21:24:20 -0800295 // add port information
296 len += smbios_write_type8(
297 current, handle,
298 smbios_type8_info,
299 ARRAY_SIZE(smbios_type8_info)
300 );
301
Morgan Jang98621382020-06-11 16:32:16 +0800302 len += create_smbios_type9(handle, current);
303
304 return len;
305}
Johnny Lin1d286682020-09-28 22:44:48 +0800306
307void smbios_fill_dimm_locator(const struct dimm_info *dimm, struct smbios_type17 *t)
308{
309 char buf[40];
310
Johnny Lin38cb7c12021-01-25 15:45:06 +0800311 snprintf(buf, sizeof(buf), "DIMM_%c0", 'A' + dimm->channel_num);
Johnny Lin1d286682020-09-28 22:44:48 +0800312 t->device_locator = smbios_add_string(t->eos, buf);
313
314 snprintf(buf, sizeof(buf), "_Node0_Channel%d_Dimm0", dimm->channel_num);
315 t->bank_locator = smbios_add_string(t->eos, buf);
316}
Morgan Jang98621382020-06-11 16:32:16 +0800317
Johnny Lin407b35a2020-05-12 10:05:27 +0800318static void mainboard_enable(struct device *dev)
319{
Elyes Haouas7ac796c2022-09-29 12:46:46 +0200320 dev->ops->get_smbios_strings = dl_oem_smbios_strings;
Johnny Lin407b35a2020-05-12 10:05:27 +0800321 read_fru_areas(CONFIG_BMC_KCS_BASE, CONFIG_FRU_DEVICE_ID, 0, &fru_strings);
Morgan Jang98621382020-06-11 16:32:16 +0800322 dev->ops->get_smbios_data = mainboard_smbios_data;
Johnny Lin407b35a2020-05-12 10:05:27 +0800323}
324
Jonathan Zhang826523b2020-04-09 10:42:19 -0700325void mainboard_silicon_init_params(FSPS_UPD *params)
326{
Bryant Ou9ccd3112020-07-16 20:19:17 -0700327 /* configure Lewisburg PCH GPIO controller after FSP-M */
328 gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
Jonathan Zhang826523b2020-04-09 10:42:19 -0700329}
Johnny Lin407b35a2020-05-12 10:05:27 +0800330
331static void mainboard_final(void *chip_info)
332{
Johnny Lin407b35a2020-05-12 10:05:27 +0800333}
334
335struct chip_operations mainboard_ops = {
336 .enable_dev = mainboard_enable,
337 .final = mainboard_final,
338};
Arthur Heymans8c6ee912021-02-02 19:16:08 +0100339
Patrick Rudolph7a593ab2024-01-25 15:15:00 +0100340void smm_mainboard_pci_resource_store_init(struct smm_pci_resource_info *slots, size_t size)
341{
342 soc_ubox_store_resources(slots, size);
343}
344
Arthur Heymans8c6ee912021-02-02 19:16:08 +0100345bool skip_intel_txt_lockdown(void)
346{
347 static bool fetched_vpd = 0;
348 static uint8_t skip_txt = SKIP_INTEL_TXT_LOCKDOWN_DEFAULT;
349
350 if (fetched_vpd)
351 return (bool)skip_txt;
352
353 if (!vpd_get_bool(SKIP_INTEL_TXT_LOCKDOWN, VPD_RW_THEN_RO, &skip_txt))
354 printk(BIOS_INFO, "%s: not able to get VPD %s, default set to %d\n",
355 __func__, SKIP_INTEL_TXT_LOCKDOWN, SKIP_INTEL_TXT_LOCKDOWN_DEFAULT);
356 else
357 printk(BIOS_DEBUG, "%s: VPD %s, got %d\n", __func__, SKIP_INTEL_TXT_LOCKDOWN,
358 skip_txt);
359
360 fetched_vpd = 1;
361
362 return (bool)skip_txt;
363}