blob: c24d004ed04a4be0a1533408bff8d102310c23f0 [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>
7#include <cpxsp_dl_gpio.h>
8#include <device/device.h>
9#include <device/pci_def.h>
10#include <device/pci_ops.h>
Johnny Lin407b35a2020-05-12 10:05:27 +080011#include <drivers/ipmi/ipmi_ops.h>
12#include <drivers/ocp/dmi/ocp_dmi.h>
Arthur Heymans8c6ee912021-02-02 19:16:08 +010013#include <drivers/vpd/vpd.h>
Morgan Jang98621382020-06-11 16:32:16 +080014#include <hob_iiouds.h>
Johnny Lin9da02792020-08-18 19:09:10 +080015#include <hob_memmap.h>
Elyes Haouas9efe34a2022-10-10 11:27:56 +020016#include <security/intel/txt/txt.h>
17#include <smbios.h>
18#include <soc/ramstage.h>
19#include <soc/soc_util.h>
20#include <soc/util.h>
21#include <stdio.h>
22#include <string.h>
23#include <types.h>
Jonathan Zhang826523b2020-04-09 10:42:19 -070024
Johnny Lin407b35a2020-05-12 10:05:27 +080025#include "ipmi.h"
Arthur Heymans8c6ee912021-02-02 19:16:08 +010026#include "vpd.h"
Johnny Lin407b35a2020-05-12 10:05:27 +080027
Johnny Lin5e8709f2020-06-11 15:25:37 +080028#define SLOT_ID_LEN 2
29
Johnny Lin407b35a2020-05-12 10:05:27 +080030extern struct fru_info_str fru_strings;
Johnny Lin5e8709f2020-06-11 15:25:37 +080031static char slot_id_str[SLOT_ID_LEN];
32
33/* Override SMBIOS 2 Location In Chassis from BMC */
34const char *smbios_mainboard_location_in_chassis(void)
35{
36 uint8_t slot_id = 0;
37
38 if (ipmi_get_slot_id(&slot_id) != CB_SUCCESS) {
39 printk(BIOS_ERR, "IPMI get slot_id failed\n");
40 return "";
41 }
42 /* Sanity check, slot_id can only be 1~4 since there are 4 slots in YV3 */
43 if (slot_id < PCIE_CONFIG_A || slot_id > PCIE_CONFIG_D) {
44 printk(BIOS_ERR, "slot_id %d is not between 1~4\n", slot_id);
45 return "";
46 }
47 snprintf(slot_id_str, SLOT_ID_LEN, "%d", slot_id);
48 return slot_id_str;
49}
Johnny Lin407b35a2020-05-12 10:05:27 +080050
Tim Chue82aa222020-12-21 23:33:18 -080051/* Override SMBIOS type 2 Feature Flags */
52u8 smbios_mainboard_feature_flags(void)
53{
54 return SMBIOS_FEATURE_FLAGS_HOSTING_BOARD | SMBIOS_FEATURE_FLAGS_REPLACEABLE;
55}
56
Tim Chube34afa2020-11-13 03:04:54 -080057/*
58 * Override SMBIOS type 4 cpu voltage.
59 * BIT7 will set to 1 after value return. If BIT7 is set to 1, the remaining seven
60 * bits of this field are set to contain the processor's current voltage times 10.
61 */
62unsigned int smbios_cpu_get_voltage(void)
63{
64 /* This will return 1.6V which is expected value for Delta Lake
65 10h = (1.6 * 10) = 16 */
66 return 0x10;
67}
68
Morgan Jang98621382020-06-11 16:32:16 +080069/* System Slot Socket, Stack, Type and Data bus width Information */
70typedef struct {
71 u8 stack;
72 u8 slot_type;
73 u8 slot_data_bus_width;
74 u8 dev_func;
75 const char *slot_designator;
76} slot_info;
77
JingleHsuWiwynn20fa59f2021-01-26 09:55:34 +080078/* Array index + 1 would be used as Slot ID */
Morgan Jang98621382020-06-11 16:32:16 +080079slot_info slotinfo[] = {
Jingle Hsu5b24c6d2020-10-07 16:02:51 +080080 {CSTACK, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0xE8, "SSD1_M2_Data_Drive"},
81 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x10, "SSD0_M2_Boot_Drive"},
82 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x18, "BB_OCP_NIC"},
Johnny Linc8ea2122021-03-10 11:15:53 +080083 {PSTACK2, SlotTypePciExpressGen3X16, SlotDataBusWidth16X, 0x00, "1OU_OCP_NIC"},
Jingle Hsu5b24c6d2020-10-07 16:02:51 +080084 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x00, "2OU_JD1_M2_0"},
85 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x08, "2OU_JD1_M2_1"},
Johnny Linc8ea2122021-03-10 11:15:53 +080086 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x08, "2OU_JD2_M2_2"},
87 {PSTACK1, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x00, "2OU_JD2_M2_3"},
Jingle Hsu5b24c6d2020-10-07 16:02:51 +080088 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x10, "2OU_JD3_M2_4"},
89 {PSTACK0, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x18, "2OU_JD3_M2_5"},
Johnny Linc8ea2122021-03-10 11:15:53 +080090 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x18, "1OU_JD1_M2_0"},
91 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x10, "1OU_JD1_M2_1"},
92 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x08, "1OU_JD2_M2_2"},
93 {PSTACK2, SlotTypePciExpressGen3X4, SlotDataBusWidth4X, 0x00, "1OU_JD2_M2_3"},
Morgan Jang98621382020-06-11 16:32:16 +080094};
95
Johnny Lin9da02792020-08-18 19:09:10 +080096#define SPD_REGVID_LEN 6
97/* A 4-digit long number plus a space */
98static void write_oem_word(uint16_t val, char *str)
99{
100 snprintf(str, SPD_REGVID_LEN, "%04x ", val);
101}
102
Johnny Lin407b35a2020-05-12 10:05:27 +0800103static void dl_oem_smbios_strings(struct device *dev, struct smbios_type11 *t)
104{
105 uint8_t pcie_config = 0;
Johnny Lin9da02792020-08-18 19:09:10 +0800106 const struct SystemMemoryMapHob *hob;
107 char spd_reg_vid[SPD_REGVID_LEN];
108 char empty[1] = "";
109 char *oem_str7 = empty;
Johnny Lin407b35a2020-05-12 10:05:27 +0800110
111 /* OEM string 1 to 6 */
112 ocp_oem_smbios_strings(dev, t);
113
Johnny Lin9da02792020-08-18 19:09:10 +0800114 /* OEM string 7 is the register vendor ID in SPD for each DIMM strung together */
115 hob = get_system_memory_map();
Elyes Haouas3de12532022-09-13 10:14:27 +0200116 assert(hob);
Johnny Lin9da02792020-08-18 19:09:10 +0800117 /* There are at most 6 channels and 2 DIMMs per channel, but Delta Lake has 6 DIMMs,
118 e.g. b300 0000 b300 0000 b300 0000 b300 0000 b300 0000 b300 0000 */
119 for (int ch = 0; ch < MAX_CH; ch++) {
120 for (int dimm = 0; dimm < MAX_IMC; dimm++) {
121 write_oem_word(hob->Socket[0].ChannelInfo[ch].DimmInfo[dimm].SPDRegVen,
122 spd_reg_vid);
123 oem_str7 = strconcat(oem_str7, spd_reg_vid);
124 }
125 }
126 t->count = smbios_add_oem_string(t->eos, oem_str7);
Johnny Lin407b35a2020-05-12 10:05:27 +0800127
128 /* Add OEM string 8 */
129 if (ipmi_get_pcie_config(&pcie_config) == CB_SUCCESS) {
130 switch (pcie_config) {
131 case PCIE_CONFIG_UNKNOWN:
132 t->count = smbios_add_oem_string(t->eos, "0x0: Unknown");
133 break;
134 case PCIE_CONFIG_A:
135 t->count = smbios_add_oem_string(t->eos, "0x1: YV3 Config-A");
136 break;
137 case PCIE_CONFIG_B:
138 t->count = smbios_add_oem_string(t->eos, "0x2: YV3 Config-B");
139 break;
140 case PCIE_CONFIG_C:
141 t->count = smbios_add_oem_string(t->eos, "0x3: YV3 Config-C");
142 break;
143 case PCIE_CONFIG_D:
144 t->count = smbios_add_oem_string(t->eos, "0x4: YV3 Config-D");
145 break;
146 default:
147 t->count = smbios_add_oem_string(t->eos, "Check BMC return data");
148 }
149 } else {
150 printk(BIOS_ERR, "Failed to get IPMI PCIe config\n");
151 }
152}
153
Tim Chu39ea2232020-11-23 21:24:20 -0800154static const struct port_information smbios_type8_info[] = {
155 {
156 .internal_reference_designator = "JCN18 - CPU MIPI60",
157 .internal_connector_type = CONN_OTHER,
158 .external_reference_designator = "",
159 .external_connector_type = CONN_NONE,
160 .port_type = TYPE_OTHER_PORT
161 },
162 {
163 .internal_reference_designator = "JCN32 - TPM_CONN",
164 .internal_connector_type = CONN_OTHER,
165 .external_reference_designator = "",
166 .external_connector_type = CONN_NONE,
167 .port_type = TYPE_OTHER_PORT
168 },
169 {
170 .internal_reference_designator = "JCN7 - USB type C",
171 .internal_connector_type = CONN_USB_TYPE_C,
172 .external_reference_designator = "",
173 .external_connector_type = CONN_NONE,
174 .port_type = TYPE_USB
175 },
176};
177
Morgan Jang98621382020-06-11 16:32:16 +0800178static int create_smbios_type9(int *handle, unsigned long *current)
179{
180 int index;
181 int length = 0;
182 uint8_t slot_length;
183 uint8_t sec_bus;
184 uint8_t slot_usage;
185 uint8_t pcie_config = 0;
Morgan Jang98621382020-06-11 16:32:16 +0800186 uint32_t vendor_device_id;
Maxim Polyakov91a45122021-01-14 01:37:26 +0300187 uint8_t stack_busnos[MAX_IIO_STACK];
Johnny Lincfe15a22021-10-05 08:33:08 +0800188 pci_devfn_t pci_dev_slot, pci_dev = 0;
Morgan Jang98621382020-06-11 16:32:16 +0800189 unsigned int cap;
190 uint16_t sltcap;
191
192 if (ipmi_get_pcie_config(&pcie_config) != CB_SUCCESS)
193 printk(BIOS_ERR, "Failed to get IPMI PCIe config\n");
194
Maxim Polyakov91a45122021-01-14 01:37:26 +0300195 for (index = 0; index < ARRAY_SIZE(stack_busnos); index++)
196 stack_busnos[index] = get_stack_busno(index);
Morgan Jang98621382020-06-11 16:32:16 +0800197
198 for (index = 0; index < ARRAY_SIZE(slotinfo); index++) {
Johnny Lincfe15a22021-10-05 08:33:08 +0800199 uint8_t characteristics_1 = 0;
200 uint8_t characteristics_2 = 0;
201
Morgan Jang98621382020-06-11 16:32:16 +0800202 if (pcie_config == PCIE_CONFIG_A) {
Jingle Hsu5b24c6d2020-10-07 16:02:51 +0800203 if (index == 0 || index == 1 || index == 2)
Morgan Jang98621382020-06-11 16:32:16 +0800204 printk(BIOS_INFO, "Find Config-A slot: %s\n",
205 slotinfo[index].slot_designator);
206 else
207 continue;
208 }
209 if (pcie_config == PCIE_CONFIG_B) {
Johnny Linc8ea2122021-03-10 11:15:53 +0800210 switch (index) {
211 case 0 ... 2:
212 case 10 ... 13:
Morgan Jang98621382020-06-11 16:32:16 +0800213 printk(BIOS_INFO, "Find Config-B slot: %s\n",
214 slotinfo[index].slot_designator);
Johnny Linc8ea2122021-03-10 11:15:53 +0800215 break;
216 default:
Morgan Jang98621382020-06-11 16:32:16 +0800217 continue;
Johnny Linc8ea2122021-03-10 11:15:53 +0800218 }
Morgan Jang98621382020-06-11 16:32:16 +0800219 }
220 if (pcie_config == PCIE_CONFIG_C) {
Johnny Linc8ea2122021-03-10 11:15:53 +0800221 switch (index) {
222 case 0 ... 1:
223 case 3 ... 9:
Morgan Jang98621382020-06-11 16:32:16 +0800224 printk(BIOS_INFO, "Find Config-C slot: %s\n",
225 slotinfo[index].slot_designator);
Johnny Linc8ea2122021-03-10 11:15:53 +0800226 break;
227 default:
Morgan Jang98621382020-06-11 16:32:16 +0800228 continue;
Johnny Linc8ea2122021-03-10 11:15:53 +0800229 }
Morgan Jang98621382020-06-11 16:32:16 +0800230 }
231 if (pcie_config == PCIE_CONFIG_D) {
Johnny Linc8ea2122021-03-10 11:15:53 +0800232 if (index != 3)
Morgan Jang98621382020-06-11 16:32:16 +0800233 printk(BIOS_INFO, "Find Config-D slot: %s\n",
234 slotinfo[index].slot_designator);
235 else
236 continue;
237 }
238
239 if (slotinfo[index].slot_data_bus_width == SlotDataBusWidth16X)
240 slot_length = SlotLengthLong;
241 else
242 slot_length = SlotLengthShort;
243
Johnny Lincfe15a22021-10-05 08:33:08 +0800244 pci_dev_slot = PCI_DEV(stack_busnos[slotinfo[index].stack],
Morgan Jang98621382020-06-11 16:32:16 +0800245 slotinfo[index].dev_func >> 3, slotinfo[index].dev_func & 0x7);
Johnny Lincfe15a22021-10-05 08:33:08 +0800246 sec_bus = pci_s_read_config8(pci_dev_slot, PCI_SECONDARY_BUS);
Morgan Jang98621382020-06-11 16:32:16 +0800247
248 if (sec_bus == 0xFF) {
249 slot_usage = SlotUsageUnknown;
250 } else {
Johnny Lincfe15a22021-10-05 08:33:08 +0800251 /* Checking for downstream device availability */
Morgan Jang98621382020-06-11 16:32:16 +0800252 pci_dev = PCI_DEV(sec_bus, 0, 0);
253 vendor_device_id = pci_s_read_config32(pci_dev, 0);
254 if (vendor_device_id == 0xFFFFFFFF)
255 slot_usage = SlotUsageAvailable;
256 else
257 slot_usage = SlotUsageInUse;
258 }
259
260 characteristics_1 |= SMBIOS_SLOT_3P3V; // Provides33Volts
261 characteristics_2 |= SMBIOS_SLOT_PME; // PmeSiganalSupported
Johnny Lincfe15a22021-10-05 08:33:08 +0800262 /* Read IIO root port device CSR for slot capabilities */
263 cap = pci_s_find_capability(pci_dev_slot, PCI_CAP_ID_PCIE);
264 sltcap = pci_s_read_config16(pci_dev_slot, cap + PCI_EXP_SLTCAP);
Morgan Jang98621382020-06-11 16:32:16 +0800265 if (sltcap & PCI_EXP_SLTCAP_HPC)
266 characteristics_2 |= SMBIOS_SLOT_HOTPLUG;
267
JingleHsuWiwynn20fa59f2021-01-26 09:55:34 +0800268 const uint16_t slot_id = index + 1;
Johnny Lincfe15a22021-10-05 08:33:08 +0800269 /* According to SMBIOS spec, the BDF number should be the end
270 point on the slot, for now we keep using the root port's BDF to
271 be aligned with our UEFI reference BIOS. */
Morgan Jang98621382020-06-11 16:32:16 +0800272 length += smbios_write_type9(current, handle,
273 slotinfo[index].slot_designator,
274 slotinfo[index].slot_type,
275 slotinfo[index].slot_data_bus_width,
276 slot_usage,
277 slot_length,
JingleHsuWiwynn20fa59f2021-01-26 09:55:34 +0800278 slot_id,
Morgan Jang98621382020-06-11 16:32:16 +0800279 characteristics_1,
280 characteristics_2,
Felix Heldd4594032024-01-11 21:50:36 +0100281 0, /* segment group */
Morgan Jang98621382020-06-11 16:32:16 +0800282 stack_busnos[slotinfo[index].stack],
283 slotinfo[index].dev_func);
284 }
285
286 return length;
287}
288
289static int mainboard_smbios_data(struct device *dev, int *handle, unsigned long *current)
290{
291 int len = 0;
292
Tim Chu39ea2232020-11-23 21:24:20 -0800293 // add port information
294 len += smbios_write_type8(
295 current, handle,
296 smbios_type8_info,
297 ARRAY_SIZE(smbios_type8_info)
298 );
299
Morgan Jang98621382020-06-11 16:32:16 +0800300 len += create_smbios_type9(handle, current);
301
302 return len;
303}
Johnny Lin1d286682020-09-28 22:44:48 +0800304
305void smbios_fill_dimm_locator(const struct dimm_info *dimm, struct smbios_type17 *t)
306{
307 char buf[40];
308
Johnny Lin38cb7c12021-01-25 15:45:06 +0800309 snprintf(buf, sizeof(buf), "DIMM_%c0", 'A' + dimm->channel_num);
Johnny Lin1d286682020-09-28 22:44:48 +0800310 t->device_locator = smbios_add_string(t->eos, buf);
311
312 snprintf(buf, sizeof(buf), "_Node0_Channel%d_Dimm0", dimm->channel_num);
313 t->bank_locator = smbios_add_string(t->eos, buf);
314}
Morgan Jang98621382020-06-11 16:32:16 +0800315
Johnny Lin407b35a2020-05-12 10:05:27 +0800316static void mainboard_enable(struct device *dev)
317{
Elyes Haouas7ac796c2022-09-29 12:46:46 +0200318 dev->ops->get_smbios_strings = dl_oem_smbios_strings;
Johnny Lin407b35a2020-05-12 10:05:27 +0800319 read_fru_areas(CONFIG_BMC_KCS_BASE, CONFIG_FRU_DEVICE_ID, 0, &fru_strings);
Morgan Jang98621382020-06-11 16:32:16 +0800320 dev->ops->get_smbios_data = mainboard_smbios_data;
Johnny Lin407b35a2020-05-12 10:05:27 +0800321}
322
Jonathan Zhang826523b2020-04-09 10:42:19 -0700323void mainboard_silicon_init_params(FSPS_UPD *params)
324{
Bryant Ou9ccd3112020-07-16 20:19:17 -0700325 /* configure Lewisburg PCH GPIO controller after FSP-M */
326 gpio_configure_pads(gpio_table, ARRAY_SIZE(gpio_table));
Jonathan Zhang826523b2020-04-09 10:42:19 -0700327}
Johnny Lin407b35a2020-05-12 10:05:27 +0800328
329static void mainboard_final(void *chip_info)
330{
Johnny Lin407b35a2020-05-12 10:05:27 +0800331}
332
333struct chip_operations mainboard_ops = {
334 .enable_dev = mainboard_enable,
335 .final = mainboard_final,
336};
Arthur Heymans8c6ee912021-02-02 19:16:08 +0100337
338bool skip_intel_txt_lockdown(void)
339{
340 static bool fetched_vpd = 0;
341 static uint8_t skip_txt = SKIP_INTEL_TXT_LOCKDOWN_DEFAULT;
342
343 if (fetched_vpd)
344 return (bool)skip_txt;
345
346 if (!vpd_get_bool(SKIP_INTEL_TXT_LOCKDOWN, VPD_RW_THEN_RO, &skip_txt))
347 printk(BIOS_INFO, "%s: not able to get VPD %s, default set to %d\n",
348 __func__, SKIP_INTEL_TXT_LOCKDOWN, SKIP_INTEL_TXT_LOCKDOWN_DEFAULT);
349 else
350 printk(BIOS_DEBUG, "%s: VPD %s, got %d\n", __func__, SKIP_INTEL_TXT_LOCKDOWN,
351 skip_txt);
352
353 fetched_vpd = 1;
354
355 return (bool)skip_txt;
356}