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-or-later */
2 
3 #include <arch/romstage.h>
4 #include <device/pci_ops.h>
5 #include <arch/symbols.h>
6 #include <assert.h>
7 #include <cf9_reset.h>
8 #include <console/console.h>
9 #include <device/device.h>
10 #include <cpu/x86/pae.h>
11 #include <delay.h>
12 #include <device/pci_def.h>
13 #include <device/resource.h>
14 #include <fsp/api.h>
15 #include <fsp/util.h>
16 #include <intelblocks/cpulib.h>
17 #include <intelblocks/lpc_lib.h>
18 #include <intelblocks/msr.h>
19 #include <intelblocks/pmclib.h>
21 #include <mrc_cache.h>
22 #include <soc/cpu.h>
23 #include <soc/iomap.h>
24 #include <soc/meminit.h>
25 #include <soc/pci_devs.h>
26 #include <soc/pm.h>
27 #include <soc/romstage.h>
28 #include <soc/systemagent.h>
29 #include <spi_flash.h>
30 #include <timer.h>
31 #include "chip.h"
32 
33 static const uint8_t hob_variable_guid[16] = {
34  0x7d, 0x14, 0x34, 0xa0, 0x0c, 0x69, 0x54, 0x41,
35  0x8d, 0xe6, 0xc0, 0x44, 0x64, 0x1d, 0xe9, 0x42,
36 };
37 
39 
40 /* High Performance Event Timer Configuration */
41 #define P2SB_HPTC 0x60
42 #define P2SB_HPTC_ADDRESS_ENABLE (1 << 7)
43 /*
44  * ADDRESS_SELECT ENCODING_RANGE
45  * 0 0xFED0 0000 - 0xFED0 03FF
46  * 1 0xFED0 1000 - 0xFED0 13FF
47  * 2 0xFED0 2000 - 0xFED0 23FF
48  * 3 0xFED0 3000 - 0xFED0 33FF
49  */
50 #define P2SB_HPTC_ADDRESS_SELECT_0 (0 << 0)
51 #define P2SB_HPTC_ADDRESS_SELECT_1 (1 << 0)
52 #define P2SB_HPTC_ADDRESS_SELECT_2 (2 << 0)
53 #define P2SB_HPTC_ADDRESS_SELECT_3 (3 << 0)
54 
55 /*
56  * Enables several BARs and devices which are needed for memory init
57  * - MCH_BASE_ADDR is needed in order to talk to the memory controller
58  * - HPET is enabled because FSP wants to store a pointer to global data in the
59  * HPET comparator register
60  */
61 static void soc_early_romstage_init(void)
62 {
63  static const struct sa_mmio_descriptor soc_fixed_pci_resources[] = {
64  { MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" },
65  };
66 
67  /* Set Fixed MMIO address into PCI configuration space */
68  sa_set_pci_bar(soc_fixed_pci_resources,
69  ARRAY_SIZE(soc_fixed_pci_resources));
70 
71  /* Enable decoding for HPET. Needed for FSP global pointer storage */
74 }
75 
76 /*
77  * Punit Initialization code. This all isn't documented, but
78  * this is the recipe.
79  */
80 static bool punit_init(void)
81 {
82  uint32_t reg;
83  uint32_t data;
84  struct stopwatch sw;
85 
86  /* Thermal throttle activation offset */
88 
89  /*
90  * Software Core Disable Mask (P_CR_CORE_DISABLE_MASK_0_0_0_MCHBAR).
91  * Enable all cores here.
92  */
94 
95  /* P-Unit bring up */
96  reg = MCHBAR32(BIOS_RESET_CPL);
97  if (reg == 0xffffffff) {
98  /* P-unit not found */
99  printk(BIOS_DEBUG, "Punit MMIO not available\n");
100  return false;
101  }
102  /* Set Punit interrupt pin IPIN offset 3D */
104 
105  /* Set PUINT IRQ to 24 and INTPIN LOCK */
109 
110  if (!CONFIG(SOC_INTEL_GEMINILAKE)) {
111  data = MCHBAR32(0x7818);
112  data &= 0xFFFFE01F;
113  data |= 0x20 | 0x200;
114  MCHBAR32(0x7818) = data;
115  }
116 
117  /* Stage0 BIOS Reset Complete (RST_CPL) */
119 
120  /*
121  * Poll for bit 8 to check if PCODE has completed its action
122  * in response to BIOS Reset complete.
123  * We wait here till 1 ms for the bit to get set.
124  */
126  while (!(MCHBAR32(BIOS_RESET_CPL) & PCODE_INIT_DONE)) {
127  if (stopwatch_expired(&sw)) {
128  printk(BIOS_DEBUG, "PCODE Init Done Failure\n");
129  return false;
130  }
131  udelay(100);
132  }
133 
134  return true;
135 }
136 
137 void set_max_freq(void)
138 {
140  /* Burst Mode has been factory configured as disabled
141  * and is not available in this physical processor
142  * package.
143  */
144  printk(BIOS_DEBUG, "Burst Mode is factory disabled\n");
145  return;
146  }
147 
148  /* Enable burst mode */
149  cpu_burst_mode(true);
150 
151  /* Enable speed step. */
152  cpu_set_eist(true);
153 
154  /* Set P-State ratio */
156 }
157 
159 {
160  bool s3wake;
161  size_t var_size;
163  const void *new_var_data;
164 
167 
168  s3wake = pmc_fill_power_state(ps) == ACPI_S3;
169  fsp_memory_init(s3wake);
170 
171  if (punit_init())
172  set_max_freq();
173  else
174  printk(BIOS_DEBUG, "Punit failed to initialize properly\n");
175 
176  /* Stash variable MRC data and let cache system update it later */
178  &var_size);
179  if (new_var_data)
181  fsp_version, new_var_data,
182  var_size);
183  else
184  printk(BIOS_ERR, "Failed to determine variable data\n");
185 
187 }
188 
189 static void fill_console_params(FSPM_UPD *mupd)
190 {
191  if (CONFIG(CONSOLE_SERIAL)) {
192  if (CONFIG(INTEL_LPSS_UART_FOR_CONSOLE)) {
193  mupd->FspmConfig.SerialDebugPortDevice =
194  CONFIG_UART_FOR_CONSOLE;
195  /* use MMIO port type */
196  mupd->FspmConfig.SerialDebugPortType = 2;
197  /* use 4 byte register stride */
198  mupd->FspmConfig.SerialDebugPortStrideSize = 2;
199  /* used only for port type set to external */
200  mupd->FspmConfig.SerialDebugPortAddress = 0;
201  } else if (CONFIG(DRIVERS_UART_8250IO)) {
202  /* use external UART for debug */
203  mupd->FspmConfig.SerialDebugPortDevice = 3;
204  /* use I/O port type */
205  mupd->FspmConfig.SerialDebugPortType = 1;
206  /* use 1 byte register stride */
207  mupd->FspmConfig.SerialDebugPortStrideSize = 0;
208  /* used only for port type set to external */
209  mupd->FspmConfig.SerialDebugPortAddress =
210  CONFIG_TTYS0_BASE;
211  }
212  } else {
213  mupd->FspmConfig.SerialDebugPortType = 0;
214  }
215 }
216 
217 static void check_full_retrain(const FSPM_UPD *mupd)
218 {
219  struct chipset_power_state *ps;
220 
221  if (mupd->FspmArchUpd.BootMode != FSP_BOOT_WITH_FULL_CONFIGURATION)
222  return;
223 
224  ps = pmc_get_power_state();
225 
226  if (ps->gen_pmcon1 & WARM_RESET_STS) {
227  printk(BIOS_INFO, "Full retrain unsupported on warm reboot.\n");
228  full_reset();
229  }
230 }
231 
232 static void soc_gpu_init_params(FSPM_UPD *mupd)
233 {
234  enum {
235  GPU_PRIMARY_IGD = 0,
236  GPU_PRIMARY_PCI = 1,
237  };
238  /* Select primary GPU device */
239  if (CONFIG(ONBOARD_VGA_IS_PRIMARY) && is_devfn_enabled(SA_DEVFN_IGD))
240  mupd->FspmConfig.PrimaryVideoAdaptor = GPU_PRIMARY_IGD;
241  else
242  mupd->FspmConfig.PrimaryVideoAdaptor = GPU_PRIMARY_PCI;
243 }
244 
245 static void soc_memory_init_params(FSPM_UPD *mupd)
246 {
247 #if CONFIG(SOC_INTEL_GEMINILAKE)
248  /* Only for GLK */
249  FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
250 
251  m_cfg->PrmrrSize = get_valid_prmrr_size();
252 
253  /*
254  * CpuMemoryTest in FSP tests 0 to 1M of the RAM after MRC init.
255  * With PAGING_IN_CACHE_AS_RAM enabled for GLK, there was no page
256  * table entry for this range which caused a page fault. Since this
257  * test is anyway not exhaustive, skipping the memory test in FSP.
258  */
259  m_cfg->SkipMemoryTestUpd = 1;
260 
261  /*
262  * PCIe power sequence can be done from within FSP when provided
263  * with the GPIOs used for PERST to FSP. Since this is done in
264  * coreboot, skipping the PCIe power sequence done by FSP.
265  */
266  m_cfg->SkipPciePowerSequence = 1;
267 #endif
268 }
269 
270 static void parse_devicetree_setting(FSPM_UPD *m_upd)
271 {
272 #if CONFIG(SOC_INTEL_GEMINILAKE)
273  m_upd->FspmConfig.TraceHubEn = is_devfn_enabled(PCH_DEVFN_NPK);
274 #else
275  m_upd->FspmConfig.NpkEn = is_devfn_enabled(PCH_DEVFN_NPK);
276 #endif
277 }
278 
280 {
281  check_full_retrain(mupd);
282 
283  fill_console_params(mupd);
284  soc_gpu_init_params(mupd);
285 
286  if (CONFIG(SOC_INTEL_GEMINILAKE))
288 
290 
292 
293  /* Do NOT let FSP do any GPIO pad configuration */
294  mupd->FspmConfig.PreMemGpioTablePtr = (uintptr_t) NULL;
295 
296  mupd->FspmConfig.SkipCseRbp = CONFIG(SKIP_CSE_RBP);
297 
298  /*
299  * Converged Security Engine (CSE) has secure storage functionality.
300  * HECI2 device can be used to access that functionality. However, part
301  * of S3 resume flow involves resetting HECI2 which takes 136ms. Since
302  * coreboot does not use secure storage functionality, instruct FSP to
303  * skip HECI2 reset.
304  */
305  mupd->FspmConfig.EnableS3Heci2 = 0;
306 
307  /*
308  * Apollolake splits MRC cache into two parts: constant and variable.
309  * The constant part is not expected to change often and variable is.
310  * Currently variable part consists of parameters that change on cold
311  * boots such as scrambler seed and some memory controller registers.
312  * Scrambler seed is vital for S3 resume case because attempt to use
313  * wrong/missing key renders DRAM contents useless.
314  */
315 
316  mupd->FspmConfig.VariableNvsBufferPtr =
318  NULL);
319 
320  assert(CONFIG(BOOT_DEVICE_MEMORY_MAPPED));
321 
323 
324 }
325 
326 __weak
327 void mainboard_memory_init_params(FSPM_UPD *mupd)
328 {
329  printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
330 }
331 
332 __weak
334 {
335  printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__);
336 }
#define WARM_RESET_STS
Definition: pm.h:158
#define CORE_DISABLE_MASK
Definition: systemagent.h:15
#define PUNIT_THERMAL_DEVICE_IRQ
Definition: systemagent.h:9
#define PUINT_THERMAL_DEVICE_IRQ_VEC_NUMBER
Definition: systemagent.h:10
#define PCODE_INIT_DONE
Definition: systemagent.h:13
#define PUINT_THERMAL_DEVICE_IRQ_LOCK
Definition: systemagent.h:11
#define assert(statement)
Definition: assert.h:74
#define ARRAY_SIZE(a)
Definition: helpers.h:12
void full_reset(void)
Definition: cf9_reset.c:45
void enable_bios_reset_cpl(void)
#define MCHBAR32(x)
Definition: systemagent.h:23
void sa_set_pci_bar(const struct sa_mmio_descriptor *fixed_set_resources, size_t count)
#define printk(level,...)
Definition: stdlib.h:16
void set_max_freq(void)
Definition: romstage.c:7
void cpu_set_eist(bool eist_status)
Definition: cpulib.c:250
int cpu_get_burst_mode_state(void)
Definition: cpulib.c:172
void configure_tcc_thermal_target(void)
Definition: cpulib.c:317
void cpu_set_p_state_to_turbo_ratio(void)
Definition: cpulib.c:103
int get_valid_prmrr_size(void)
Definition: cpulib.c:397
void cpu_burst_mode(bool burst_mode_status)
Definition: cpulib.c:233
@ BURST_MODE_UNAVAILABLE
Definition: cpulib.h:94
bool is_devfn_enabled(unsigned int devfn)
Definition: device_const.c:382
__weak void mainboard_save_dimm_info(struct romstage_params *params)
Definition: romstage.c:138
@ CONFIG
Definition: dsi_common.h:201
@ FSP_BOOT_WITH_FULL_CONFIGURATION
Definition: api.h:19
void fsp_memory_init(bool s3wake)
Definition: memory_init.c:350
#define FSP_M_CONFIG
Definition: fsp_upd.h:8
const void * fsp_find_extension_hob_by_guid(const uint8_t *guid, size_t *size)
#define MCHBAR
Definition: host_bridge.h:7
#define BIOS_RESET_CPL
Definition: mchbar.h:62
@ ACPI_S3
Definition: acpi.h:1383
static __always_inline void pci_write_config8(const struct device *dev, u16 reg, u8 val)
Definition: pci_ops.h:64
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
#define MCH_BASE_ADDRESS
Definition: iomap.h:82
unsigned int version[2]
Definition: edid.c:55
#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
void mainboard_memory_init_params(FSPM_UPD *mupd)
Definition: romstage.c:22
void mainboard_romstage_entry(void)
Definition: romstage.c:6
int mrc_cache_stash_data(int type, uint32_t version, const void *data, size_t size)
Returns < 0 on error, 0 on success.
Definition: mrc_cache.c:687
void * mrc_cache_current_mmap_leak(int type, uint32_t version, size_t *data_size)
mrc_cache_mmap_leak
Definition: mrc_cache.c:342
@ MRC_VARIABLE_DATA
Definition: mrc_cache.h:12
void report_platform_info(void)
#define MCH_BASE_SIZE
Definition: memmap.h:6
#define PCI_INTERRUPT_PIN
Definition: pci_def.h:95
const struct smm_save_state_ops *legacy_ops __weak
Definition: save_state.c:8
#define PCH_DEV_P2SB
Definition: pci_devs.h:225
#define SA_DEVFN_IGD
Definition: pci_devs.h:32
#define SA_DEV_PUNIT
Definition: pci_devs.h:27
#define PCH_DEVFN_NPK
Definition: pci_devs.h:44
static void soc_early_romstage_init(void)
Definition: romstage.c:61
static bool punit_init(void)
Definition: romstage.c:80
#define P2SB_HPTC
Definition: romstage.c:41
static void fill_console_params(FSPM_UPD *mupd)
Definition: romstage.c:189
static uint32_t fsp_version
Definition: romstage.c:38
static const uint8_t hob_variable_guid[16]
Definition: romstage.c:33
#define P2SB_HPTC_ADDRESS_ENABLE
Definition: romstage.c:42
static void soc_gpu_init_params(FSPM_UPD *mupd)
Definition: romstage.c:232
static void check_full_retrain(const FSPM_UPD *mupd)
Definition: romstage.c:217
void platform_fsp_memory_init_params_cb(FSPM_UPD *mupd, uint32_t version)
Definition: romstage.c:279
#define P2SB_HPTC_ADDRESS_SELECT_0
Definition: romstage.c:50
static void soc_memory_init_params(FSPM_UPD *mupd)
Definition: romstage.c:245
static void parse_devicetree_setting(FSPM_UPD *m_upd)
Definition: romstage.c:270
int pmc_fill_power_state(struct chipset_power_state *ps)
Definition: pmclib.c:437
struct chipset_power_state * pmc_get_power_state(void)
Definition: pmclib.c:58
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
unsigned long uintptr_t
Definition: stdint.h:21
unsigned char uint8_t
Definition: stdint.h:8
uint32_t gen_pmcon1
Definition: pm.h:231
void udelay(uint32_t us)
Definition: udelay.c:15