coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
romstage.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <console/console.h>
4 #include <console/uart.h>
7 #include <drivers/vpd/vpd.h>
8 #include <fsp/api.h>
9 #include <FspmUpd.h>
10 #include <soc/romstage.h>
11 #include <FspmUpdHelper.h>
12 
13 #include "chip.h"
14 #include "ipmi.h"
15 #include "vpd.h"
16 
17 /* Convert the vpd integer to the DDR frenquency limit enum */
18 static enum ddr_freq_limit ddr_freq_limit(int num)
19 {
20  switch (num) {
21  case 0:
22  return DDR_AUTO;
23  case 1:
24  return DDR_1333;
25  case 2:
26  return DDR_1600;
27  case 3:
28  return DDR_1866;
29  case 4:
30  return DDR_2133;
31  case 5:
32  return DDR_2400;
33  case 6:
34  return DDR_2666;
35  case 7:
36  return DDR_2933;
37  case 8:
38  return DDR_3200;
39  default:
40  printk(BIOS_WARNING, "Invalid DdrFreqLimit value from VPD: "
41  "%d\n", num);
42  return DDR_AUTO;
43  };
44 }
45 
46 /*
47  * Search from VPD_RW first then VPD_RO for UPD config variables,
48  * overwrites them from VPD if it's found.
49  */
50 static void mainboard_config_upd(FSPM_UPD *mupd)
51 {
52  uint8_t val;
53  int val_int;
54 
55  /* Send FSP log message to SOL */
57  mupd->FspmConfig.SerialIoUartDebugEnable = val;
58  else {
59  printk(BIOS_INFO, "Not able to get VPD %s, default set "
60  "SerialIoUartDebugEnable to %d\n", FSP_LOG, FSP_LOG_DEFAULT);
61  mupd->FspmConfig.SerialIoUartDebugEnable = FSP_LOG_DEFAULT;
62  }
63 
64  /* Select UART IO of FSP */
65  static const unsigned int bases[] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
66  mupd->FspmConfig.SerialIoUartDebugIoBase = bases[get_uart_for_console()];
67 
68  if (mupd->FspmConfig.SerialIoUartDebugEnable) {
69  /* FSP debug log level */
70  if (vpd_get_int(FSP_LOG_LEVEL, VPD_RW_THEN_RO, &val_int)) {
71  if (val_int < 0 || val_int > 0x0f) {
72  printk(BIOS_DEBUG, "Invalid DebugPrintLevel value from VPD: "
73  "%d\n", val_int);
74  val_int = FSP_LOG_LEVEL_DEFAULT;
75  }
76  printk(BIOS_DEBUG, "Setting DebugPrintLevel %d from VPD\n", val_int);
77  mupd->FspmConfig.DebugPrintLevel = (uint8_t)val_int;
78  } else {
79  printk(BIOS_INFO, "Not able to get VPD %s, default set "
80  "DebugPrintLevel to %d\n", FSP_LOG_LEVEL,
82  mupd->FspmConfig.DebugPrintLevel = FSP_LOG_LEVEL_DEFAULT;
83  }
84  }
85 
86  /* Enable DCI */
88  printk(BIOS_DEBUG, "Setting DciEn %d from VPD\n", val);
89  mupd->FspmConfig.PchDciEn = val;
90  } else {
91  printk(BIOS_INFO, "Not able to get VPD %s, default set "
92  "DciEn to %d\n", FSP_DCI, FSP_DCI_DEFAULT);
93  mupd->FspmConfig.PchDciEn = FSP_DCI_DEFAULT;
94  }
95 
96  /*
97  * UnusedUpdSpace0[0] is reserved for Memory Refresh Watermark.
98  * Following code is effective when MemRefreshWaterMark patch is added to FSP
99  * and when corresponding VPD variable is set.
100  */
102  if (val_int < 0 || val_int > 2) {
103  printk(BIOS_DEBUG, "Invalid MemRefreshWatermark value from VPD: "
104  "%d\n", val_int);
106  }
107  printk(BIOS_DEBUG, "Setting MemRefreshWatermark %d from VPD\n", val_int);
108  mupd->FspmConfig.UnusedUpdSpace0[0] = (uint8_t)val_int;
109  }
110 
111  /* Select DDR Frequency Limit */
112  if (vpd_get_int(FSP_DIMM_FREQ, VPD_RW_THEN_RO, (int *const) &val_int)) {
113  printk(BIOS_INFO, "Setting DdrFreqLimit %d from VPD\n", val_int);
114  mupd->FspmConfig.DdrFreqLimit = ddr_freq_limit(val_int);
115  } else {
116  printk(BIOS_WARNING, "Not able to get VPD %s, default set "
117  "DdrFreqLimit to %d\n", FSP_DIMM_FREQ,
119  mupd->FspmConfig.DdrFreqLimit = ddr_freq_limit(FSP_DIMM_FREQ_DEFAULT);
120  }
121 }
122 
123 /* Update bifurcation settings according to different Configs */
124 static void oem_update_iio(FSPM_UPD *mupd)
125 {
126  uint8_t pcie_config = 0;
127 
128  /* Default set to PCIE_CONFIG_C first */
129  mupd->FspmConfig.IioConfigIOU0[0] = IIO_BIFURCATE_x4x4x4x4;
130  mupd->FspmConfig.IioConfigIOU1[0] = IIO_BIFURCATE_x4x4x4x4;
131  mupd->FspmConfig.IioConfigIOU2[0] = IIO_BIFURCATE_xxxxxxxx;
132  mupd->FspmConfig.IioConfigIOU3[0] = IIO_BIFURCATE_xxxxxx16;
133  mupd->FspmConfig.IioConfigIOU4[0] = IIO_BIFURCATE_xxxxxxxx;
134  /* Update IIO bifurcation according to different Configs */
135  if (ipmi_get_pcie_config(&pcie_config) == CB_SUCCESS) {
136  printk(BIOS_DEBUG, "get IPMI PCIe config: %d\n", pcie_config);
137  switch (pcie_config) {
138  case PCIE_CONFIG_A:
139  mupd->FspmConfig.IioConfigIOU0[0] = IIO_BIFURCATE_xxxxxxxx;
140  mupd->FspmConfig.IioConfigIOU3[0] = IIO_BIFURCATE_xxxxxxxx;
141  break;
142  case PCIE_CONFIG_B:
143  mupd->FspmConfig.IioConfigIOU0[0] = IIO_BIFURCATE_xxxxxxxx;
144  mupd->FspmConfig.IioConfigIOU3[0] = IIO_BIFURCATE_x4x4x4x4;
145  break;
146  case PCIE_CONFIG_D:
147  mupd->FspmConfig.IioConfigIOU3[0] = IIO_BIFURCATE_x4x4x4x4;
148  break;
149  case PCIE_CONFIG_C:
150  default:
151  break;
152  }
153  } else {
154  printk(BIOS_ERR, "%s failed to get IPMI PCIe config\n", __func__);
155  }
156 }
157 
158 /*
159 * Configure GPIO depend on platform
160 */
161 static void mainboard_config_gpios(FSPM_UPD *mupd)
162 {
163  /* To be implemented */
164 }
165 
166 static void mainboard_config_iio(FSPM_UPD *mupd)
167 {
168  uint8_t index;
169  const config_t *config = config_of_soc();
170 
171  oem_update_iio(mupd);
172 
173  for (index = 0; index < MAX_PCH_PCIE_PORT; index++) {
174  mupd->FspmConfig.PchPcieForceEnable[index] =
175  config->pch_pci_port[index].ForceEnable;
176  mupd->FspmConfig.PchPciePortLinkSpeed[index] =
177  config->pch_pci_port[index].PortLinkSpeed;
178  }
179 
180  mupd->FspmConfig.PchPcieRootPortFunctionSwap = 0x00;
181  /* The default value is 0XFF in FSP, set it to 0xFE by platform */
182  mupd->FspmConfig.PchPciePllSsc = 0xFE;
183 }
184 
185 void mainboard_memory_init_params(FSPM_UPD *mupd)
186 {
187  uint8_t val;
188 
189  /* Since it's the first IPMI command, it's better to run get BMC
190  selftest result first */
191  if (ipmi_kcs_premem_init(CONFIG_BMC_KCS_BASE, 0) == CB_SUCCESS) {
192  ipmi_set_post_start(CONFIG_BMC_KCS_BASE);
193  init_frb2_wdt();
194  }
195 
196  /* Enable force memory training */
198  if (mupd->FspmArchUpd.NvsBufferPtr && val) {
199  mupd->FspmArchUpd.NvsBufferPtr = 0;
200  printk(BIOS_DEBUG, "Force Memory Training...Start\n");
201  }
202  }
203 
205  mainboard_config_iio(mupd);
206  mainboard_config_upd(mupd);
207 }
208 
210 {
212  printk(BIOS_DEBUG, "%s: IPMI set cmos clear successful\n", __func__);
213  else
214  printk(BIOS_ERR, "%s: IPMI set cmos clear failed\n", __func__);
215 }
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
#define printk(level,...)
Definition: stdlib.h:16
void init_frb2_wdt(void)
Definition: ipmi.c:60
enum cb_err ipmi_get_pcie_config(uint8_t *pcie_config)
Definition: ipmi.c:12
@ PCIE_CONFIG_A
Definition: ipmi.h:14
@ PCIE_CONFIG_C
Definition: ipmi.h:16
@ PCIE_CONFIG_B
Definition: ipmi.h:15
@ PCIE_CONFIG_D
Definition: ipmi.h:17
@ VPD_RW_THEN_RO
Definition: vpd.h:14
#define config_of_soc()
Definition: device.h:394
enum cb_err ipmi_kcs_premem_init(const u16 port, const u16 device)
enum cb_err ipmi_set_post_start(const int port)
enum cb_err ipmi_set_cmos_clear(void)
#define BIOS_INFO
BIOS_INFO - Expected events.
Definition: loglevel.h:113
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
void mainboard_memory_init_params(FSPM_UPD *mupd)
Definition: romstage.c:22
enum board_config config
Definition: memory.c:448
void mainboard_config_gpios(void)
Definition: romstage.c:70
static enum ddr_freq_limit ddr_freq_limit(int num)
Definition: romstage.c:18
static void mainboard_config_upd(FSPM_UPD *mupd)
Definition: romstage.c:50
void mainboard_rtc_failed(void)
Definition: romstage.c:209
static void mainboard_config_iio(FSPM_UPD *mupd)
Definition: romstage.c:166
static void oem_update_iio(FSPM_UPD *mupd)
Definition: romstage.c:124
#define FSP_LOG_DEFAULT
Definition: vpd.h:22
#define FSPM_MEMREFRESHWATERMARK
Definition: vpd.h:37
#define FSPM_MEMREFRESHWATERMARK_DEFAULT
Definition: vpd.h:38
#define MEM_TRAIN_FORCE
Definition: vpd.h:54
#define FSP_DCI
Definition: vpd.h:29
#define FSP_DIMM_FREQ_DEFAULT
Definition: vpd.h:47
#define FSP_LOG_LEVEL
Definition: vpd.h:25
#define FSP_DCI_DEFAULT
Definition: vpd.h:30
#define FSP_DIMM_FREQ
Definition: vpd.h:46
#define FSP_LOG
Definition: vpd.h:21
#define FSP_LOG_LEVEL_DEFAULT
Definition: vpd.h:26
#define MAX_PCH_PCIE_PORT
Definition: chip.h:12
ddr_freq_limit
enum for DDR Frequency Limit
Definition: chip.h:37
@ DDR_2933
Definition: chip.h:45
@ DDR_3200
Definition: chip.h:46
@ DDR_1333
Definition: chip.h:39
@ DDR_2400
Definition: chip.h:43
@ DDR_AUTO
Definition: chip.h:38
@ DDR_2666
Definition: chip.h:44
@ DDR_1866
Definition: chip.h:41
@ DDR_1600
Definition: chip.h:40
@ DDR_2133
Definition: chip.h:42
unsigned char uint8_t
Definition: stdint.h:8
u8 val
Definition: sys.c:300
static const unsigned int bases[]
Definition: uart8250io.c:75
unsigned int get_uart_for_console(void)
Definition: uartio_vpd.c:8
bool vpd_get_int(const char *const key, const enum vpd_region region, int *const val)
Definition: vpd.c:284
bool vpd_get_bool(const char *key, enum vpd_region region, uint8_t *val)
Definition: vpd.c:252