Timothy Pearson (tpearson(a)raptorengineering.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16306
-gerrit
commit 830a3dd5364dfa373490e1506ec9cb557ed3942f
Author: Timothy Pearson <tpearson(a)raptorengineering.com>
Date: Tue Aug 23 15:41:05 2016 -0500
sb/amd/sb700: Add option to increase SPI speed to 33MHz
Some SB700-based systems and ROMs support high speed (33MHz) SPI
access instead of the power-on default 16.5MHz. Add an option
to enable high speed SPI access in the bootblock, and set the
default value to Disabled. This greatly decreases boot time on
SB700-based systems, especiall when a large payload is in use.
On a KGPE-D16 with a Petitboot (Linux + initramfs) payload, the
command prompt was accessible within 20 seconds of power on, which
incidentally is faster than the proprietary BIOS on the same machine
could even reach the GRUB bootloader.
Change-Id: Iadbd9bb611754262ef75a5e5a6ee4390a46e45cf
Signed-off-by: Timothy Pearson <tpearson(a)raptorengineering.com>
Test: Booted KGPE-D16 with Linux payload
---
src/southbridge/amd/sb700/Kconfig | 10 ++++++++++
src/southbridge/amd/sb700/bootblock.c | 34 ++++++++++++++++++++++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/src/southbridge/amd/sb700/Kconfig b/src/southbridge/amd/sb700/Kconfig
index 9a988a9..353c2a4 100644
--- a/src/southbridge/amd/sb700/Kconfig
+++ b/src/southbridge/amd/sb700/Kconfig
@@ -25,6 +25,16 @@ config SOUTHBRIDGE_SPECIFIC_OPTIONS # dummy
select HAVE_HARD_RESET
select SMBUS_HAS_AUX_CHANNELS
+config SOUTHBRIDGE_AMD_SB700_33MHZ_SPI
+ bool "Enable high speed SPI clock"
+ default n
+ help
+ When set, the SPI clock will run at 33MHz instead
+ of the compatibility mode 16.5MHz. Note that not
+ all ROMs are capable of 33MHz operation, so you
+ will need to verify this option is appropriate for
+ the ROM you are using.
+
# Set for southbridge SP5100 which also uses SB700 driver
config SOUTHBRIDGE_AMD_SUBTYPE_SP5100
bool
diff --git a/src/southbridge/amd/sb700/bootblock.c b/src/southbridge/amd/sb700/bootblock.c
index 97e749c..dfa4102 100644
--- a/src/southbridge/amd/sb700/bootblock.c
+++ b/src/southbridge/amd/sb700/bootblock.c
@@ -20,6 +20,10 @@
#define IO_MEM_PORT_DECODE_ENABLE_5 0x48
#define IO_MEM_PORT_DECODE_ENABLE_6 0x4a
+#define SPI_BASE_ADDRESS 0xa0
+
+#define SPI_CONTROL_1 0xc
+#define TEMPORARY_SPI_BASE_ADDRESS 0xfec10000
/*
* Enable 4MB (LPC) ROM access at 0xFFC00000 - 0xFFFFFFFF.
@@ -92,7 +96,37 @@ static void sb700_enable_rom(void)
pci_io_write_config8(dev, IO_MEM_PORT_DECODE_ENABLE_6, reg8);
}
+static void sb700_configure_rom(void)
+{
+ pci_devfn_t dev;
+ uint32_t dword;
+
+ dev = PCI_DEV(0, 0x14, 3);
+
+ if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_33MHZ_SPI)) {
+ uint32_t prev_spi_cfg;
+ volatile uint32_t *spi_mmio;
+
+ /* Temporarily set up SPI access to change SPI speed */
+ prev_spi_cfg = dword = pci_io_read_config32(dev, SPI_BASE_ADDRESS);
+ dword &= ~(0x7ffffff << 5); /* SPI_BaseAddr */
+ dword |= TEMPORARY_SPI_BASE_ADDRESS & (0x7ffffff << 5);
+ dword |= (0x1 << 1); /* SpiRomEnable = 1 */
+ pci_io_write_config32(dev, SPI_BASE_ADDRESS, dword);
+
+ spi_mmio = (void *)(TEMPORARY_SPI_BASE_ADDRESS + SPI_CONTROL_1);
+ dword = *spi_mmio;
+ dword &= ~(0x3 << 12); /* NormSpeed = 0x1 */
+ dword |= (0x1 << 12);
+ *spi_mmio = dword;
+
+ /* Restore previous SPI access */
+ pci_io_write_config32(dev, SPI_BASE_ADDRESS, prev_spi_cfg);
+ }
+}
+
static void bootblock_southbridge_init(void)
{
sb700_enable_rom();
+ sb700_configure_rom();
}
Timothy Pearson (tpearson(a)raptorengineering.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16306
-gerrit
commit 0f4cafdb69ce54e8fd89684c6c17bc5b6b650d9a
Author: Timothy Pearson <tpearson(a)raptorengineering.com>
Date: Tue Aug 23 15:41:05 2016 -0500
sb/amd/sb700: Add option to increase SPI speed to 33MHz
Some SB700-based systems and ROMs support high speed (33MHz) SPI
access instead of the power-on default 16.5MHz. Add an option
to enable high speed SPI access in the bootblock, and set the
default value to Disabled. This greatly decreases boot time on
SB700-based systems, especiall when a large payload is in use.
On a KGPE-D16 with a Petitboot (Linux + initramfs) payload, the
command prompt was accessible within 20 seconds of power on, which
incidentally is faster than the proprietary BIOS on the same machine
could even reach the GRUB bootloader.
Change-Id: Iadbd9bb611754262ef75a5e5a6ee4390a46e45cf
Signed-off-by: Timothy Pearson <tpearson(a)raptorengineering.com>
Test: Booted KGPE-D16 with Linux payload
---
src/southbridge/amd/sb700/Kconfig | 10 ++++++++++
src/southbridge/amd/sb700/bootblock.c | 29 +++++++++++++++++++++++++++++
2 files changed, 39 insertions(+)
diff --git a/src/southbridge/amd/sb700/Kconfig b/src/southbridge/amd/sb700/Kconfig
index 9a988a9..353c2a4 100644
--- a/src/southbridge/amd/sb700/Kconfig
+++ b/src/southbridge/amd/sb700/Kconfig
@@ -25,6 +25,16 @@ config SOUTHBRIDGE_SPECIFIC_OPTIONS # dummy
select HAVE_HARD_RESET
select SMBUS_HAS_AUX_CHANNELS
+config SOUTHBRIDGE_AMD_SB700_33MHZ_SPI
+ bool "Enable high speed SPI clock"
+ default n
+ help
+ When set, the SPI clock will run at 33MHz instead
+ of the compatibility mode 16.5MHz. Note that not
+ all ROMs are capable of 33MHz operation, so you
+ will need to verify this option is appropriate for
+ the ROM you are using.
+
# Set for southbridge SP5100 which also uses SB700 driver
config SOUTHBRIDGE_AMD_SUBTYPE_SP5100
bool
diff --git a/src/southbridge/amd/sb700/bootblock.c b/src/southbridge/amd/sb700/bootblock.c
index 97e749c..88ee0ac 100644
--- a/src/southbridge/amd/sb700/bootblock.c
+++ b/src/southbridge/amd/sb700/bootblock.c
@@ -20,6 +20,10 @@
#define IO_MEM_PORT_DECODE_ENABLE_5 0x48
#define IO_MEM_PORT_DECODE_ENABLE_6 0x4a
+#define SPI_BASE_ADDRESS 0xa0
+
+#define SPI_CONTROL_1 0xc
+#define TEMPORARY_SPI_BASE_ADDRESS 0xfec10000
/*
* Enable 4MB (LPC) ROM access at 0xFFC00000 - 0xFFFFFFFF.
@@ -92,7 +96,32 @@ static void sb700_enable_rom(void)
pci_io_write_config8(dev, IO_MEM_PORT_DECODE_ENABLE_6, reg8);
}
+static void sb700_configure_rom(void)
+{
+ if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_33MHZ_SPI)) {
+ uint32_t prev_spi_cfg;
+ volatile uint32_t *spi_mmio;
+
+ /* Temporarily set up SPI access to change SPI speed */
+ prev_spi_cfg = dword = pci_io_read_config32(dev, SPI_BASE_ADDRESS);
+ dword &= ~(0x7ffffff << 5); /* SPI_BaseAddr */
+ dword |= TEMPORARY_SPI_BASE_ADDRESS & (0x7ffffff << 5);
+ dword |= (0x1 << 1); /* SpiRomEnable = 1 */
+ pci_io_write_config32(dev, SPI_BASE_ADDRESS, dword);
+
+ spi_mmio = (void *)(TEMPORARY_SPI_BASE_ADDRESS + SPI_CONTROL_1);
+ dword = *spi_mmio;
+ dword &= ~(0x3 << 12); /* NormSpeed = 0x1 */
+ dword |= (0x1 << 12);
+ *spi_mmio = dword;
+
+ /* Restore previous SPI access */
+ pci_io_write_config32(dev, SPI_BASE_ADDRESS, prev_spi_cfg);
+ }
+}
+
static void bootblock_southbridge_init(void)
{
sb700_enable_rom();
+ sb700_configure_rom();
}
Timothy Pearson (tpearson(a)raptorengineering.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16306
-gerrit
commit 183f5ffcbf3dabf407a32e3ba64fae044f988063
Author: Timothy Pearson <tpearson(a)raptorengineering.com>
Date: Tue Aug 23 15:41:05 2016 -0500
sb/amd/sb700: Add option to increase SPI speed to 33MHz
Some SB700-based systems and ROMs support high speed (33MHz) SPI
access instead of the power-on default 16.5MHz. Add an option
to enable high speed SPI access in the bootblock, and set the
default value to Disabled. This greatly decreases boot time on
SB700-based systems, especiall when a large payload is in use.
On a KGPE-D16 with a Petitboot (Linux + initramfs) payload, the
command prompt was accessible within 20 seconds of power on, which
incidentally is faster than the proprietary BIOS on the same machine
could even reach the GRUB bootloader.
Change-Id: Iadbd9bb611754262ef75a5e5a6ee4390a46e45cf
Signed-off-by: Timothy Pearson <tpearson(a)raptorengineering.com>
Test: Booted KGPE-D16 with Linux payload
---
src/southbridge/amd/sb700/Kconfig | 10 ++++++++++
src/southbridge/amd/sb700/bootblock.c | 28 ++++++++++++++++++++++++++++
2 files changed, 38 insertions(+)
diff --git a/src/southbridge/amd/sb700/Kconfig b/src/southbridge/amd/sb700/Kconfig
index 9a988a9..353c2a4 100644
--- a/src/southbridge/amd/sb700/Kconfig
+++ b/src/southbridge/amd/sb700/Kconfig
@@ -25,6 +25,16 @@ config SOUTHBRIDGE_SPECIFIC_OPTIONS # dummy
select HAVE_HARD_RESET
select SMBUS_HAS_AUX_CHANNELS
+config SOUTHBRIDGE_AMD_SB700_33MHZ_SPI
+ bool "Enable high speed SPI clock"
+ default n
+ help
+ When set, the SPI clock will run at 33MHz instead
+ of the compatibility mode 16.5MHz. Note that not
+ all ROMs are capable of 33MHz operation, so you
+ will need to verify this option is appropriate for
+ the ROM you are using.
+
# Set for southbridge SP5100 which also uses SB700 driver
config SOUTHBRIDGE_AMD_SUBTYPE_SP5100
bool
diff --git a/src/southbridge/amd/sb700/bootblock.c b/src/southbridge/amd/sb700/bootblock.c
index 97e749c..2fc60b8 100644
--- a/src/southbridge/amd/sb700/bootblock.c
+++ b/src/southbridge/amd/sb700/bootblock.c
@@ -20,6 +20,10 @@
#define IO_MEM_PORT_DECODE_ENABLE_5 0x48
#define IO_MEM_PORT_DECODE_ENABLE_6 0x4a
+#define SPI_BASE_ADDRESS 0xa0
+
+#define SPI_CONTROL_1 0xc
+#define TEMPORARY_SPI_BASE_ADDRESS 0xfec10000
/*
* Enable 4MB (LPC) ROM access at 0xFFC00000 - 0xFFFFFFFF.
@@ -90,9 +94,33 @@ static void sb700_enable_rom(void)
reg8 = pci_io_read_config8(dev, IO_MEM_PORT_DECODE_ENABLE_6);
reg8 |= (1 << 5);
pci_io_write_config8(dev, IO_MEM_PORT_DECODE_ENABLE_6, reg8);
+
+static void sb700_configure_rom(void)
+{
+ if (IS_ENABLED(CONFIG_SOUTHBRIDGE_AMD_SB700_33MHZ_SPI)) {
+ uint32_t prev_spi_cfg;
+ volatile uint32_t *spi_mmio;
+
+ /* Temporarily set up SPI access to change SPI speed */
+ prev_spi_cfg = dword = pci_io_read_config32(dev, SPI_BASE_ADDRESS);
+ dword &= ~(0x7ffffff << 5); /* SPI_BaseAddr */
+ dword |= TEMPORARY_SPI_BASE_ADDRESS & (0x7ffffff << 5);
+ dword |= (0x1 << 1); /* SpiRomEnable = 1 */
+ pci_io_write_config32(dev, SPI_BASE_ADDRESS, dword);
+
+ spi_mmio = (void *)(TEMPORARY_SPI_BASE_ADDRESS + SPI_CONTROL_1);
+ dword = *spi_mmio;
+ dword &= ~(0x3 << 12); /* NormSpeed = 0x1 */
+ dword |= (0x1 << 12);
+ *spi_mmio = dword;
+
+ /* Restore previous SPI access */
+ pci_io_write_config32(dev, SPI_BASE_ADDRESS, prev_spi_cfg);
+ }
}
static void bootblock_southbridge_init(void)
{
sb700_enable_rom();
+ sb700_configure_rom();
}
Rizwan Qureshi (rizwan.qureshi(a)intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16315
-gerrit
commit 6995249ca8abd99016c03c713a789edf1845f950
Author: Barnali Sarkar <barnali.sarkar(a)intel.com>
Date: Wed Aug 24 20:48:46 2016 +0530
skylake: Add FSP 2.0 support in romstage
Setup stack and MTRRs after Dram initialization. This
setup code is present in FSP1.1 driver, copy and reuse
stack.c.
Populate SoC related Memory related params.
Make sure FSP binaries are properly relocated to the base where
they are placed in CBFS. i.e., Make them XIP.
Minor correction in top of ram calculation.
TEST=Build and boot kunimitsu, dram initialization done.
ramstage is loaded.
Change-Id: I8d943e29b6e118986189166d92c7891ab6642193
Signed-off-by: Rizwan Qureshi <rizwan.qureshi(a)intel.com>
---
src/soc/intel/skylake/Makefile.inc | 6 +
src/soc/intel/skylake/chip.h | 4 +
src/soc/intel/skylake/include/fsp20/soc/romstage.h | 9 +-
src/soc/intel/skylake/memmap.c | 19 ++-
src/soc/intel/skylake/romstage/romstage_fsp20.c | 84 +++++++++-
src/soc/intel/skylake/stack.c | 169 +++++++++++++++++++++
6 files changed, 280 insertions(+), 11 deletions(-)
diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc
index aa3da61..02b3ee8 100644
--- a/src/soc/intel/skylake/Makefile.inc
+++ b/src/soc/intel/skylake/Makefile.inc
@@ -42,6 +42,7 @@ romstage-y += pei_data.c
romstage-y += pmutil.c
romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c
romstage-y += smbus_common.c
+romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += stack.c
romstage-y += tsc_freq.c
romstage-$(CONFIG_UART_DEBUG) += uart_debug.c
@@ -104,6 +105,8 @@ CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp1_1/skylake
else
CPPFLAGS_common += -I$(src)/soc/intel/skylake/include/fsp20
CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp2_0/skykabylake
+$(CONFIG_FSP_M_CBFS)-options := --xip
+$(CONFIG_FSP_S_CBFS)-options := --xip
endif
# Currently used for microcode path.
@@ -111,4 +114,7 @@ CPPFLAGS_common += -I3rdparty/blobs/mainboard/$(MAINBOARD_DIR)
ROMCCFLAGS := -mcpu=p4 -fno-simplify-phi -O2
+$(CONFIG_FSP_M_CBFS)-options := --xip
+$(CONFIG_FSP_S_CBFS)-options := --xip
+
endif
diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h
index a4dee51..62e28e6 100644
--- a/src/soc/intel/skylake/chip.h
+++ b/src/soc/intel/skylake/chip.h
@@ -359,6 +359,10 @@ struct soc_intel_skylake_config {
* 011b - VR specific command sent for both MPS IMPV8 & PS4 exit issue
*/
u8 SendVrMbxCmd;
+
+ /* Enable/Disable VMX feature */
+ u8 VmxEnable;
+
/* Statically clock gate 8254 PIT. */
u8 clock_gate_8254;
diff --git a/src/soc/intel/skylake/include/fsp20/soc/romstage.h b/src/soc/intel/skylake/include/fsp20/soc/romstage.h
index d48ac67..253ee32 100644
--- a/src/soc/intel/skylake/include/fsp20/soc/romstage.h
+++ b/src/soc/intel/skylake/include/fsp20/soc/romstage.h
@@ -22,9 +22,16 @@
asmlinkage void *car_stage_c_entry(void);
void mainboard_memory_init_params(struct FSPM_UPD *mupd);
-
void systemagent_early_init(void);
int smbus_read_byte(unsigned device, unsigned address);
int early_spi_read_wpsr(u8 *sr);
+void *setup_stack_and_mtrrs(void);
+/* Board type */
+ enum BoardT{
+ BOARD_TYPE_MOBILE = 0,
+ BOARD_TYPE_DESKTOP = 1,
+ BOARD_TYPE_ULT_ULX = 5,
+ BOARD_TYPE_SERVER = 7
+};
#endif /* _SOC_ROMSTAGE_H_ */
diff --git a/src/soc/intel/skylake/memmap.c b/src/soc/intel/skylake/memmap.c
index 96debfd..6bc0682 100644
--- a/src/soc/intel/skylake/memmap.c
+++ b/src/soc/intel/skylake/memmap.c
@@ -144,27 +144,38 @@ u32 top_of_32bit_ram(void)
const struct device *dev;
const struct soc_intel_skylake_config *config;
+ top_of_ram = smm_region_start();
+
/*
* Check if Tseg has been initialized, we will use this as a flag
* to check if the MRC is done, and only then continue to read the
* PRMMR_BASE MSR. The system hangs if PRMRR_BASE MSR is read before
* PRMRR_MASK MSR lock bit is set.
*/
- if (smm_region_start() == 0)
+ if (top_of_ram == 0)
return 0;
dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_ROOT, 0));
config = dev->chip_info;
/*
- * On Skylake, cbmem_top is offset down from PRMRR_BASE by reserved
+ * On Kabylake, cbmem_top is offset down from PRMRR_BASE by reserved
* memory (128MiB) for CPU trace if enabled, then reserved memory (4KB)
- * for PTT if enabled. PTT is in fact not used on Skylake platforms.
+ * for PTT if enabled. PTT is in fact not used on Kabylake platforms.
* Refer to Fsp Integration Guide for the memory mapping layout.
+ * If SGX is enabled, then FSP updates PRMRR base & mask msr.
+ * Use value from PRMRR base msr to calculate top_of_ram.
+ * If PRMRR base is non-zero then top_of_ram is PRMRR base.
*/
+
prmrr_base = rdmsr(UNCORE_PRMRR_PHYS_BASE_MSR);
- top_of_ram = prmrr_base.lo;
+ if ( prmrr_base.lo != 0)
+ top_of_ram = prmrr_base.lo;
+ /*
+ * If ProbelessTrace is enabled then
+ * top_of_ram is top_of_ram minus TRACE_MEMORY_SIZE.
+ */
if (config->ProbelessTrace)
top_of_ram -= TRACE_MEMORY_SIZE;
diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c
index 8a15a69..781bfa7 100644
--- a/src/soc/intel/skylake/romstage/romstage_fsp20.c
+++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c
@@ -13,29 +13,101 @@
* GNU General Public License for more details.
*/
+#include <arch/cpu.h>
+#include <arch/early_variables.h>
+#include <arch/io.h>
+#include <arch/symbols.h>
+#include <assert.h>
+#include <cpu/x86/mtrr.h>
+#include <cbmem.h>
+#include <chip.h>
#include <console/console.h>
+#include <device/pci_def.h>
#include <fsp/util.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
#include <soc/romstage.h>
+#include <timestamp.h>
+#include <vboot/vboot_common.h>
asmlinkage void *car_stage_c_entry(void)
{
- bool s3wake = false;
+ bool s3wake;
+ void *top_of_stack;
+ struct chipset_power_state *ps;
+
console_init();
- /* TODO: Add fill_powerstate and determine sleep state. */
+
+ /* Program MCHBAR, DMIBAR, GDXBAR and EDRAMBAR */
+ systemagent_early_init();
+
+ ps = fill_power_state();
+ timestamp_add_now(TS_START_ROMSTAGE);
+ s3wake = ps->prev_sleep_state == ACPI_S3;
fsp_memory_init(s3wake);
- return NULL;
+
+ top_of_stack = setup_stack_and_mtrrs();
+ return top_of_stack;
}
+
static void soc_memory_init_params(struct FSP_M_CONFIG *m_cfg)
{
- /* TODO: Fill SoC specific Memory init Params */
-}
+ const struct device *dev;
+ const struct soc_intel_skylake_config *config;
+ int i;
+ uint32_t mask = 0;
-void platform_fsp_memory_init_params_cb(struct FSPM_UPD *mupd){
+ /* Set the parameters for MemoryInit */
+ dev = dev_find_slot(0, PCI_DEVFN(PCH_DEV_SLOT_LPC, 0));
+ config = dev->chip_info;
+ /*
+ * Set IGD stolen size to 64MB. The FBC hardware for skylake does not
+ * have access to the bios_reserved range so it always assumes 8MB is
+ * used and so the kernel will avoid the last 8MB of the stolen window.
+ * With the default stolen size of 32MB(-8MB) there is not enough space
+ * for FBC to work with a high resolution panel.
+ */
+ m_cfg->IgdDvmt50PreAlloc = 2;
+ m_cfg->MmioSize = 0x800; /* 2GB in MB */
+ m_cfg->TsegSize = CONFIG_SMM_TSEG_SIZE;
+ m_cfg->IedSize = CONFIG_IED_REGION_SIZE;
+ m_cfg->ProbelessTrace = config->ProbelessTrace;
+ m_cfg->EnableTraceHub = config->EnableTraceHub;
+ if (vboot_recovery_mode_enabled())
+ m_cfg->SaGv = 0; /* Disable SaGv in recovery mode. */
+ else
+ m_cfg->SaGv = config->SaGv;
+ m_cfg->UserBd = BOARD_TYPE_ULT_ULX; // boardtype=ULT
+ m_cfg->SpdProfileSelected=0; //default profile selected
+ m_cfg->RMT = config->Rmt;
+ m_cfg->DdrFreqLimit = config->DdrFreqLimit;
+ m_cfg->VmxEnable = config->VmxEnable;
+ for (i=0; i < ARRAY_SIZE(config->PcieRpEnable); i++){
+ if (config->PcieRpEnable[i] == 1)
+ mask|=(1<<i);
+ }
+ m_cfg->PcieRpEnableMask = mask;
+}
+void platform_fsp_memory_init_params_cb(struct FSPM_UPD *mupd)
+{
struct FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
+ struct FSP_M_TEST_CONFIG *m_t_cfg = &mupd->FspmTestConfig;
soc_memory_init_params(m_cfg);
+
+ /* Enable DMI Virtual Channel for ME */
+ m_t_cfg->DmiVcm = 0x01;
+
+ /* Enable Sending DID to ME */
+ m_t_cfg->SendDidMsg =0x01;
+ m_t_cfg->DidInitStat =0x01;
+
mainboard_memory_init_params(mupd);
+
+ /* Reserve enough memory under TOLUD to save CBMEM header */
+ mupd->FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size();
+
}
__attribute__((weak)) void mainboard_memory_init_params(struct FSPM_UPD *mupd)
diff --git a/src/soc/intel/skylake/stack.c b/src/soc/intel/skylake/stack.c
new file mode 100644
index 0000000..d5f5350
--- /dev/null
+++ b/src/soc/intel/skylake/stack.c
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include <fsp/memmap.h>
+#include <soc/romstage.h>
+#include <stdlib.h>
+#include <program_loading.h>
+#include <soc/intel/common/util.h>
+
+static inline void *stack_push32(void *stack, uint32_t value)
+{
+ uint32_t *stack32 = stack;
+
+ stack32 = &stack32[-1];
+ *stack32 = value;
+ return stack32;
+}
+
+/*
+ * setup_stack_and_mtrrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use.
+ */
+void *setup_stack_and_mtrrs(void)
+{
+ size_t alignment;
+ uint32_t aligned_ram;
+ uint32_t mtrr_mask_upper;
+ uint32_t max_mtrrs;
+ uint32_t num_mtrrs;
+ uint32_t *slot;
+ unsigned long top_of_stack;
+
+ /* Display the MTTRs */
+ soc_display_mtrrs();
+
+ /* Top of stack needs to be aligned to a 8-byte boundary. */
+ top_of_stack = romstage_ram_stack_top();
+ slot = (void *)top_of_stack;
+ num_mtrrs = 0;
+ max_mtrrs = soc_get_variable_mtrr_count(NULL);
+
+ /*
+ * The upper bits of the MTRR mask need to set according to the number
+ * of physical address bits.
+ */
+ mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
+ alignment = mmap_region_granularity();
+ aligned_ram = ALIGN_DOWN(romstage_ram_stack_bottom(), alignment);
+
+ /*
+ * The order for each MTRR is value then base with upper 32-bits of
+ * each value coming before the lower 32-bits. The reasoning for
+ * this ordering is to create a stack layout like the following:
+ *
+ * +36: MTRR mask 1 63:32
+ * +32: MTRR mask 1 31:0
+ * +28: MTRR base 1 63:32
+ * +24: MTRR base 1 31:0
+ * +20: MTRR mask 0 63:32
+ * +16: MTRR mask 0 31:0
+ * +12: MTRR base 0 63:32
+ * +8: MTRR base 0 31:0
+ * +4: Number of MTRRs to setup (described above)
+ * +0: Number of variable MTRRs to clear
+ */
+
+ /* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(CACHE_TMP_RAMTOP - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, 0 | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /*
+ * +-------------------------+ Top of RAM (aligned)
+ * | System Management Mode |
+ * | code and data | Length: CONFIG_TSEG_SIZE
+ * | (TSEG) |
+ * +-------------------------+ SMM base (aligned)
+ * | |
+ * | Chipset Reserved Memory | Length: Multiple of CONFIG_TSEG_SIZE
+ * | |
+ * +-------------------------+ top_of_ram (aligned)
+ * | |
+ * | CBMEM Root |
+ * | |
+ * +-------------------------+
+ * | |
+ * | FSP Reserved Memory |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Various CBMEM Entries |
+ * | |
+ * +-------------------------+ top_of_stack (8 byte aligned)
+ * | |
+ * | stack (CBMEM Entry) |
+ * | |
+ * +-------------------------+
+ */
+
+ /*
+ * Cache the stack and the other CBMEM entries as well as part or all
+ * of the FSP reserved memory region.
+ */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(alignment - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, aligned_ram | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+ void *smm_base;
+ size_t smm_size;
+ uint32_t tseg_base;
+
+ /*
+ * Cache the TSEG region at the top of ram. This region is not
+ * restricted to SMM mode until SMM has been relocated. By setting
+ * the region to cacheable it provides faster access when relocating
+ * the SMM handler as well as using the TSEG region for other purposes.
+ */
+ smm_region(&smm_base, &smm_size);
+ tseg_base = (uint32_t)smm_base;
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(alignment - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, tseg_base | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+#endif
+
+ /* Cache the ROM as WP just below 4GiB. */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+ num_mtrrs++;
+
+ /* Validate the MTRR usage */
+ if (num_mtrrs > max_mtrrs) {
+ printk(BIOS_ERR, "MTRRs: max = %d, used = %d, available=%d",
+ max_mtrrs, num_mtrrs, max_mtrrs - num_mtrrs);
+ die("ERROR - MTRR use count incorrect!\n");
+ }
+
+ /*
+ * Save the number of MTRRs to setup and clear. Return the stack
+ * location pointing to the number of MTRRs.
+ */
+ slot = stack_push32(slot, num_mtrrs);
+ slot = stack_push32(slot, max_mtrrs);
+ return slot;
+}
Rizwan Qureshi (rizwan.qureshi(a)intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16301
-gerrit
commit a5db310db958f53ee206a801fe9fec3106a9634d
Author: Rizwan Qureshi <rizwan.qureshi(a)intel.com>
Date: Tue Aug 23 13:38:19 2016 +0530
kunimitsu: Add initial FSP2.0 support
Add placeholders for functions required when skylake
uses FSP2.0 driver, keeping the fsp1.1 flow intact.
Change-Id: I5446f8cd093af289e0f6022b53a985fa29e32471
Signed-off-by: Rizwan Qureshi <rizwan.qureshi(a)intel.com>
---
src/mainboard/intel/kunimitsu/Makefile.inc | 4 ++++
src/mainboard/intel/kunimitsu/ramstage.c | 2 +-
src/mainboard/intel/kunimitsu/romstage_fsp20.c | 21 +++++++++++++++++++++
src/mainboard/intel/kunimitsu/spd/Makefile.inc | 2 +-
4 files changed, 27 insertions(+), 2 deletions(-)
diff --git a/src/mainboard/intel/kunimitsu/Makefile.inc b/src/mainboard/intel/kunimitsu/Makefile.inc
index cafa12c..86be420 100644
--- a/src/mainboard/intel/kunimitsu/Makefile.inc
+++ b/src/mainboard/intel/kunimitsu/Makefile.inc
@@ -34,3 +34,7 @@ ramstage-y += pei_data.c
ramstage-y += ramstage.c
smm-$(CONFIG_HAVE_SMI_HANDLER) += smihandler.c
+
+ifeq ($(CONFIG_PLATFORM_USES_FSP2_0),y)
+romstage-srcs := $(subst $(MAINBOARDDIR)/romstage.c,$(MAINBOARDDIR)/romstage_fsp20.c,$(romstage-srcs))
+endif
diff --git a/src/mainboard/intel/kunimitsu/ramstage.c b/src/mainboard/intel/kunimitsu/ramstage.c
index 563c715..44fb9cd 100644
--- a/src/mainboard/intel/kunimitsu/ramstage.c
+++ b/src/mainboard/intel/kunimitsu/ramstage.c
@@ -16,7 +16,7 @@
#include <soc/ramstage.h>
#include "gpio.h"
-void mainboard_silicon_init_params(SILICON_INIT_UPD *params)
+void mainboard_silicon_init_params(FSP_SIL_UPD *params)
{
/* Configure pads prior to SiliconInit() in case there's any
* dependencies during hardware initialization. */
diff --git a/src/mainboard/intel/kunimitsu/romstage_fsp20.c b/src/mainboard/intel/kunimitsu/romstage_fsp20.c
new file mode 100644
index 0000000..10bdd21
--- /dev/null
+++ b/src/mainboard/intel/kunimitsu/romstage_fsp20.c
@@ -0,0 +1,21 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2016 Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <soc/romstage.h>
+
+void mainboard_memory_init_params(struct FSPM_UPD *mupd)
+{
+ /* TODO: Read and copy SPD and fill up Rcomp and DQ param */
+}
diff --git a/src/mainboard/intel/kunimitsu/spd/Makefile.inc b/src/mainboard/intel/kunimitsu/spd/Makefile.inc
index 62d6fd4..0a9cb0f 100644
--- a/src/mainboard/intel/kunimitsu/spd/Makefile.inc
+++ b/src/mainboard/intel/kunimitsu/spd/Makefile.inc
@@ -14,7 +14,7 @@
## GNU General Public License for more details.
##
-romstage-y += spd.c
+romstage-$(CONFIG_PLATFORM_USES_FSP1_1) += spd.c
SPD_BIN = $(obj)/spd.bin
Rizwan Qureshi (rizwan.qureshi(a)intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/16315
-gerrit
commit 238814060a7026a55e390c52ff1956ff3433efaa
Author: Barnali Sarkar <barnali.sarkar(a)intel.com>
Date: Wed Aug 24 20:48:46 2016 +0530
skylake: Add FSP 2.0 support in romstage
Setup stack and MTRRs after Dram initialization. This
setup code is present in FSP1.1 driver, copy and reuse
stack.c.
Populate SoC related Memory related params.
Make sure FSP binaries are properly relocated to the base where
they are placed in CBFS. i.e., Make them XIP.
Minor correction in top of ram calculation.
TEST=Build and boot kunimitsu, dram initialization done.
ramstage is loaded.
Change-Id: I8d943e29b6e118986189166d92c7891ab6642193
Signed-off-by: Rizwan Qureshi <rizwan.qureshi(a)intel.com>
---
src/soc/intel/skylake/Makefile.inc | 6 +
src/soc/intel/skylake/chip.h | 4 +
src/soc/intel/skylake/include/fsp20/soc/romstage.h | 9 +-
src/soc/intel/skylake/memmap.c | 19 ++-
src/soc/intel/skylake/romstage/romstage_fsp20.c | 84 +++++++++-
src/soc/intel/skylake/stack.c | 169 +++++++++++++++++++++
6 files changed, 280 insertions(+), 11 deletions(-)
diff --git a/src/soc/intel/skylake/Makefile.inc b/src/soc/intel/skylake/Makefile.inc
index aa3da61..02b3ee8 100644
--- a/src/soc/intel/skylake/Makefile.inc
+++ b/src/soc/intel/skylake/Makefile.inc
@@ -42,6 +42,7 @@ romstage-y += pei_data.c
romstage-y += pmutil.c
romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += reset.c
romstage-y += smbus_common.c
+romstage-$(CONFIG_PLATFORM_USES_FSP2_0) += stack.c
romstage-y += tsc_freq.c
romstage-$(CONFIG_UART_DEBUG) += uart_debug.c
@@ -104,6 +105,8 @@ CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp1_1/skylake
else
CPPFLAGS_common += -I$(src)/soc/intel/skylake/include/fsp20
CPPFLAGS_common += -I$(src)/vendorcode/intel/fsp/fsp2_0/skykabylake
+$(CONFIG_FSP_M_CBFS)-options := --xip
+$(CONFIG_FSP_S_CBFS)-options := --xip
endif
# Currently used for microcode path.
@@ -111,4 +114,7 @@ CPPFLAGS_common += -I3rdparty/blobs/mainboard/$(MAINBOARD_DIR)
ROMCCFLAGS := -mcpu=p4 -fno-simplify-phi -O2
+$(CONFIG_FSP_M_CBFS)-options := --xip
+$(CONFIG_FSP_S_CBFS)-options := --xip
+
endif
diff --git a/src/soc/intel/skylake/chip.h b/src/soc/intel/skylake/chip.h
index a4dee51..62e28e6 100644
--- a/src/soc/intel/skylake/chip.h
+++ b/src/soc/intel/skylake/chip.h
@@ -359,6 +359,10 @@ struct soc_intel_skylake_config {
* 011b - VR specific command sent for both MPS IMPV8 & PS4 exit issue
*/
u8 SendVrMbxCmd;
+
+ /* Enable/Disable VMX feature */
+ u8 VmxEnable;
+
/* Statically clock gate 8254 PIT. */
u8 clock_gate_8254;
diff --git a/src/soc/intel/skylake/include/fsp20/soc/romstage.h b/src/soc/intel/skylake/include/fsp20/soc/romstage.h
index d48ac67..253ee32 100644
--- a/src/soc/intel/skylake/include/fsp20/soc/romstage.h
+++ b/src/soc/intel/skylake/include/fsp20/soc/romstage.h
@@ -22,9 +22,16 @@
asmlinkage void *car_stage_c_entry(void);
void mainboard_memory_init_params(struct FSPM_UPD *mupd);
-
void systemagent_early_init(void);
int smbus_read_byte(unsigned device, unsigned address);
int early_spi_read_wpsr(u8 *sr);
+void *setup_stack_and_mtrrs(void);
+/* Board type */
+ enum BoardT{
+ BOARD_TYPE_MOBILE = 0,
+ BOARD_TYPE_DESKTOP = 1,
+ BOARD_TYPE_ULT_ULX = 5,
+ BOARD_TYPE_SERVER = 7
+};
#endif /* _SOC_ROMSTAGE_H_ */
diff --git a/src/soc/intel/skylake/memmap.c b/src/soc/intel/skylake/memmap.c
index 96debfd..6bc0682 100644
--- a/src/soc/intel/skylake/memmap.c
+++ b/src/soc/intel/skylake/memmap.c
@@ -144,27 +144,38 @@ u32 top_of_32bit_ram(void)
const struct device *dev;
const struct soc_intel_skylake_config *config;
+ top_of_ram = smm_region_start();
+
/*
* Check if Tseg has been initialized, we will use this as a flag
* to check if the MRC is done, and only then continue to read the
* PRMMR_BASE MSR. The system hangs if PRMRR_BASE MSR is read before
* PRMRR_MASK MSR lock bit is set.
*/
- if (smm_region_start() == 0)
+ if (top_of_ram == 0)
return 0;
dev = dev_find_slot(0, PCI_DEVFN(SA_DEV_SLOT_ROOT, 0));
config = dev->chip_info;
/*
- * On Skylake, cbmem_top is offset down from PRMRR_BASE by reserved
+ * On Kabylake, cbmem_top is offset down from PRMRR_BASE by reserved
* memory (128MiB) for CPU trace if enabled, then reserved memory (4KB)
- * for PTT if enabled. PTT is in fact not used on Skylake platforms.
+ * for PTT if enabled. PTT is in fact not used on Kabylake platforms.
* Refer to Fsp Integration Guide for the memory mapping layout.
+ * If SGX is enabled, then FSP updates PRMRR base & mask msr.
+ * Use value from PRMRR base msr to calculate top_of_ram.
+ * If PRMRR base is non-zero then top_of_ram is PRMRR base.
*/
+
prmrr_base = rdmsr(UNCORE_PRMRR_PHYS_BASE_MSR);
- top_of_ram = prmrr_base.lo;
+ if ( prmrr_base.lo != 0)
+ top_of_ram = prmrr_base.lo;
+ /*
+ * If ProbelessTrace is enabled then
+ * top_of_ram is top_of_ram minus TRACE_MEMORY_SIZE.
+ */
if (config->ProbelessTrace)
top_of_ram -= TRACE_MEMORY_SIZE;
diff --git a/src/soc/intel/skylake/romstage/romstage_fsp20.c b/src/soc/intel/skylake/romstage/romstage_fsp20.c
index 8a15a69..781bfa7 100644
--- a/src/soc/intel/skylake/romstage/romstage_fsp20.c
+++ b/src/soc/intel/skylake/romstage/romstage_fsp20.c
@@ -13,29 +13,101 @@
* GNU General Public License for more details.
*/
+#include <arch/cpu.h>
+#include <arch/early_variables.h>
+#include <arch/io.h>
+#include <arch/symbols.h>
+#include <assert.h>
+#include <cpu/x86/mtrr.h>
+#include <cbmem.h>
+#include <chip.h>
#include <console/console.h>
+#include <device/pci_def.h>
#include <fsp/util.h>
+#include <soc/pci_devs.h>
+#include <soc/pm.h>
#include <soc/romstage.h>
+#include <timestamp.h>
+#include <vboot/vboot_common.h>
asmlinkage void *car_stage_c_entry(void)
{
- bool s3wake = false;
+ bool s3wake;
+ void *top_of_stack;
+ struct chipset_power_state *ps;
+
console_init();
- /* TODO: Add fill_powerstate and determine sleep state. */
+
+ /* Program MCHBAR, DMIBAR, GDXBAR and EDRAMBAR */
+ systemagent_early_init();
+
+ ps = fill_power_state();
+ timestamp_add_now(TS_START_ROMSTAGE);
+ s3wake = ps->prev_sleep_state == ACPI_S3;
fsp_memory_init(s3wake);
- return NULL;
+
+ top_of_stack = setup_stack_and_mtrrs();
+ return top_of_stack;
}
+
static void soc_memory_init_params(struct FSP_M_CONFIG *m_cfg)
{
- /* TODO: Fill SoC specific Memory init Params */
-}
+ const struct device *dev;
+ const struct soc_intel_skylake_config *config;
+ int i;
+ uint32_t mask = 0;
-void platform_fsp_memory_init_params_cb(struct FSPM_UPD *mupd){
+ /* Set the parameters for MemoryInit */
+ dev = dev_find_slot(0, PCI_DEVFN(PCH_DEV_SLOT_LPC, 0));
+ config = dev->chip_info;
+ /*
+ * Set IGD stolen size to 64MB. The FBC hardware for skylake does not
+ * have access to the bios_reserved range so it always assumes 8MB is
+ * used and so the kernel will avoid the last 8MB of the stolen window.
+ * With the default stolen size of 32MB(-8MB) there is not enough space
+ * for FBC to work with a high resolution panel.
+ */
+ m_cfg->IgdDvmt50PreAlloc = 2;
+ m_cfg->MmioSize = 0x800; /* 2GB in MB */
+ m_cfg->TsegSize = CONFIG_SMM_TSEG_SIZE;
+ m_cfg->IedSize = CONFIG_IED_REGION_SIZE;
+ m_cfg->ProbelessTrace = config->ProbelessTrace;
+ m_cfg->EnableTraceHub = config->EnableTraceHub;
+ if (vboot_recovery_mode_enabled())
+ m_cfg->SaGv = 0; /* Disable SaGv in recovery mode. */
+ else
+ m_cfg->SaGv = config->SaGv;
+ m_cfg->UserBd = BOARD_TYPE_ULT_ULX; // boardtype=ULT
+ m_cfg->SpdProfileSelected=0; //default profile selected
+ m_cfg->RMT = config->Rmt;
+ m_cfg->DdrFreqLimit = config->DdrFreqLimit;
+ m_cfg->VmxEnable = config->VmxEnable;
+ for (i=0; i < ARRAY_SIZE(config->PcieRpEnable); i++){
+ if (config->PcieRpEnable[i] == 1)
+ mask|=(1<<i);
+ }
+ m_cfg->PcieRpEnableMask = mask;
+}
+void platform_fsp_memory_init_params_cb(struct FSPM_UPD *mupd)
+{
struct FSP_M_CONFIG *m_cfg = &mupd->FspmConfig;
+ struct FSP_M_TEST_CONFIG *m_t_cfg = &mupd->FspmTestConfig;
soc_memory_init_params(m_cfg);
+
+ /* Enable DMI Virtual Channel for ME */
+ m_t_cfg->DmiVcm = 0x01;
+
+ /* Enable Sending DID to ME */
+ m_t_cfg->SendDidMsg =0x01;
+ m_t_cfg->DidInitStat =0x01;
+
mainboard_memory_init_params(mupd);
+
+ /* Reserve enough memory under TOLUD to save CBMEM header */
+ mupd->FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size();
+
}
__attribute__((weak)) void mainboard_memory_init_params(struct FSPM_UPD *mupd)
diff --git a/src/soc/intel/skylake/stack.c b/src/soc/intel/skylake/stack.c
new file mode 100644
index 0000000..d5f5350
--- /dev/null
+++ b/src/soc/intel/skylake/stack.c
@@ -0,0 +1,169 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2013 Google Inc.
+ * Copyright (C) 2015-2016 Intel Corp.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <cbmem.h>
+#include <console/console.h>
+#include <cpu/x86/mtrr.h>
+#include <fsp/memmap.h>
+#include <soc/romstage.h>
+#include <stdlib.h>
+#include <program_loading.h>
+#include <soc/intel/common/util.h>
+
+static inline void *stack_push32(void *stack, uint32_t value)
+{
+ uint32_t *stack32 = stack;
+
+ stack32 = &stack32[-1];
+ *stack32 = value;
+ return stack32;
+}
+
+/*
+ * setup_stack_and_mtrrs() determines the stack to use after
+ * cache-as-ram is torn down as well as the MTRR settings to use.
+ */
+void *setup_stack_and_mtrrs(void)
+{
+ size_t alignment;
+ uint32_t aligned_ram;
+ uint32_t mtrr_mask_upper;
+ uint32_t max_mtrrs;
+ uint32_t num_mtrrs;
+ uint32_t *slot;
+ unsigned long top_of_stack;
+
+ /* Display the MTTRs */
+ soc_display_mtrrs();
+
+ /* Top of stack needs to be aligned to a 8-byte boundary. */
+ top_of_stack = romstage_ram_stack_top();
+ slot = (void *)top_of_stack;
+ num_mtrrs = 0;
+ max_mtrrs = soc_get_variable_mtrr_count(NULL);
+
+ /*
+ * The upper bits of the MTRR mask need to set according to the number
+ * of physical address bits.
+ */
+ mtrr_mask_upper = (1 << ((cpuid_eax(0x80000008) & 0xff) - 32)) - 1;
+ alignment = mmap_region_granularity();
+ aligned_ram = ALIGN_DOWN(romstage_ram_stack_bottom(), alignment);
+
+ /*
+ * The order for each MTRR is value then base with upper 32-bits of
+ * each value coming before the lower 32-bits. The reasoning for
+ * this ordering is to create a stack layout like the following:
+ *
+ * +36: MTRR mask 1 63:32
+ * +32: MTRR mask 1 31:0
+ * +28: MTRR base 1 63:32
+ * +24: MTRR base 1 31:0
+ * +20: MTRR mask 0 63:32
+ * +16: MTRR mask 0 31:0
+ * +12: MTRR base 0 63:32
+ * +8: MTRR base 0 31:0
+ * +4: Number of MTRRs to setup (described above)
+ * +0: Number of variable MTRRs to clear
+ */
+
+ /* Cache RAM as WB from 0 -> CACHE_TMP_RAMTOP. */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(CACHE_TMP_RAMTOP - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, 0 | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+ /*
+ * +-------------------------+ Top of RAM (aligned)
+ * | System Management Mode |
+ * | code and data | Length: CONFIG_TSEG_SIZE
+ * | (TSEG) |
+ * +-------------------------+ SMM base (aligned)
+ * | |
+ * | Chipset Reserved Memory | Length: Multiple of CONFIG_TSEG_SIZE
+ * | |
+ * +-------------------------+ top_of_ram (aligned)
+ * | |
+ * | CBMEM Root |
+ * | |
+ * +-------------------------+
+ * | |
+ * | FSP Reserved Memory |
+ * | |
+ * +-------------------------+
+ * | |
+ * | Various CBMEM Entries |
+ * | |
+ * +-------------------------+ top_of_stack (8 byte aligned)
+ * | |
+ * | stack (CBMEM Entry) |
+ * | |
+ * +-------------------------+
+ */
+
+ /*
+ * Cache the stack and the other CBMEM entries as well as part or all
+ * of the FSP reserved memory region.
+ */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(alignment - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, aligned_ram | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+
+#if IS_ENABLED(CONFIG_HAVE_SMI_HANDLER)
+ void *smm_base;
+ size_t smm_size;
+ uint32_t tseg_base;
+
+ /*
+ * Cache the TSEG region at the top of ram. This region is not
+ * restricted to SMM mode until SMM has been relocated. By setting
+ * the region to cacheable it provides faster access when relocating
+ * the SMM handler as well as using the TSEG region for other purposes.
+ */
+ smm_region(&smm_base, &smm_size);
+ tseg_base = (uint32_t)smm_base;
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(alignment - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, tseg_base | MTRR_TYPE_WRBACK);
+ num_mtrrs++;
+#endif
+
+ /* Cache the ROM as WP just below 4GiB. */
+ slot = stack_push32(slot, mtrr_mask_upper); /* upper mask */
+ slot = stack_push32(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_PHYS_MASK_VALID);
+ slot = stack_push32(slot, 0); /* upper base */
+ slot = stack_push32(slot, ~(CONFIG_ROM_SIZE - 1) | MTRR_TYPE_WRPROT);
+ num_mtrrs++;
+
+ /* Validate the MTRR usage */
+ if (num_mtrrs > max_mtrrs) {
+ printk(BIOS_ERR, "MTRRs: max = %d, used = %d, available=%d",
+ max_mtrrs, num_mtrrs, max_mtrrs - num_mtrrs);
+ die("ERROR - MTRR use count incorrect!\n");
+ }
+
+ /*
+ * Save the number of MTRRs to setup and clear. Return the stack
+ * location pointing to the number of MTRRs.
+ */
+ slot = stack_push32(slot, num_mtrrs);
+ slot = stack_push32(slot, max_mtrrs);
+ return slot;
+}