summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi.c64
-rw-r--r--src/soc/intel/common/block/fast_spi/fast_spi_def.h5
-rw-r--r--src/soc/intel/common/block/include/intelblocks/fast_spi.h5
3 files changed, 73 insertions, 1 deletions
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi.c b/src/soc/intel/common/block/fast_spi/fast_spi.c
index 4190253dd1..24c667b845 100644
--- a/src/soc/intel/common/block/fast_spi/fast_spi.c
+++ b/src/soc/intel/common/block/fast_spi/fast_spi.c
@@ -7,6 +7,7 @@
#include <commonlib/helpers.h>
#include <cpu/x86/mtrr.h>
#include <fast_spi_def.h>
+#include <intelblocks/dmi.h>
#include <intelblocks/fast_spi.h>
#include <lib.h>
#include <soc/pci_devs.h>
@@ -247,6 +248,63 @@ void fast_spi_cache_bios_region(void)
}
/*
+ * Enable extended BIOS support
+ * Checks BIOS region in the flashmap, if its more than 16Mib, enables extended BIOS
+ * region support.
+ */
+static void fast_spi_enable_ext_bios(void)
+{
+#if defined(__SIMPLE_DEVICE__)
+ pci_devfn_t dev = PCH_DEV_SPI;
+#else
+ struct device *dev = PCH_DEV_SPI;
+#endif
+ if (!CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW))
+ return;
+
+#if CONFIG(FAST_SPI_SUPPORTS_EXT_BIOS_WINDOW)
+ /*
+ * Ensure that the base for the extended window in host space is a multiple of 32 MiB
+ * and size is fixed at 32 MiB. Controller assumes that the extended window has a fixed
+ * size of 32 MiB even if the actual BIOS region is smaller. The mapping of the BIOS
+ * region happens at the top of the extended window in this case.
+ */
+ _Static_assert(ALIGN_UP(CONFIG_EXT_BIOS_WIN_BASE, 32 * MiB) == CONFIG_EXT_BIOS_WIN_BASE,
+ "Extended BIOS window base must be a multiple of 32 * MiB!");
+ _Static_assert(CONFIG_EXT_BIOS_WIN_SIZE == (32 * MiB),
+ "Only 32MiB windows are supported for extended BIOS!");
+#endif
+
+ /* Confgiure DMI Source decode for Extended BIOS Region */
+ if (dmi_enable_gpmr(CONFIG_EXT_BIOS_WIN_BASE, CONFIG_EXT_BIOS_WIN_SIZE,
+ soc_get_spi_dmi_destination_id()) == CB_ERR)
+ return;
+
+ /* Program EXT_BIOS_BAR1 with obtained ext_bios_base */
+ pci_write_config32(dev, SPI_CFG_BAR1,
+ CONFIG_EXT_BIOS_WIN_BASE | PCI_BASE_ADDRESS_SPACE_MEMORY);
+
+ /*
+ * Since the top 16MiB of the BIOS region is always decoded by the standard window
+ * below the 4G boundary, we need to map the rest of the BIOS region that lies
+ * below the top 16MiB in the extended window. Thus, EXT_BIOS_LIMIT will be set to
+ * 16MiB. This determines the maximum address in the SPI flash space that is mapped
+ * to the top of the extended window in the host address space. EXT_BIOS_LIMIT is
+ * basically the offset from the end of the BIOS region that will be mapped to the top
+ * of the extended window.
+ * This enables the decoding as follows:
+ -Standard decode window: (bios_region_top - 16MiB) to bios_region_top
+ -Extended decode window:
+ (bios_region_top - 16MiB - MIN(extended_window_size, bios_size - 16MiB))
+ to (bios_region_top - 16MiB).
+ */
+ pci_or_config32(dev, SPIBAR_BIOS_CONTROL, SPIBAR_BIOS_CONTROL_EXT_BIOS_LIMIT(16 * MiB));
+
+ /* Program EXT_BIOS EN */
+ pci_or_config32(dev, SPIBAR_BIOS_CONTROL, SPIBAR_BIOS_CONTROL_EXT_BIOS_ENABLE);
+}
+
+/*
* Program temporary BAR for SPI in case any of the stages before ramstage need
* to access FAST_SPI MMIO regs. Ramstage will assign a new BAR during PCI
* enumeration.
@@ -270,6 +328,12 @@ void fast_spi_early_init(uintptr_t spi_base_address)
pci_write_config32(dev, PCI_BASE_ADDRESS_0,
spi_base_address | PCI_BASE_ADDRESS_SPACE_MEMORY);
+ /*
+ * Enable extended bios support. Since it configures memory BAR, this is done before
+ * enabling MMIO space.
+ */
+ fast_spi_enable_ext_bios();
+
/* Enable Bus Master and MMIO Space */
pci_or_config16(dev, PCI_COMMAND, PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY);
diff --git a/src/soc/intel/common/block/fast_spi/fast_spi_def.h b/src/soc/intel/common/block/fast_spi/fast_spi_def.h
index bafe131877..883c3ce3eb 100644
--- a/src/soc/intel/common/block/fast_spi/fast_spi_def.h
+++ b/src/soc/intel/common/block/fast_spi/fast_spi_def.h
@@ -8,6 +8,9 @@
#define SPIDVID_OFFSET 0x0
#define SPIBAR_BIOS_CONTROL 0xdc
+/* Extended Bios Support Registers */
+#define SPI_CFG_BAR1 0xe0 /* SPI BAR1 MMIO */
+
/* Bit definitions for BIOS_CONTROL */
#define SPIBAR_BIOS_CONTROL_WPD (1 << 0)
#define SPIBAR_BIOS_CONTROL_LOCK_ENABLE (1 << 1)
@@ -15,6 +18,8 @@
#define SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE (1 << 3)
#define SPIBAR_BIOS_CONTROL_EISS (1 << 5)
#define SPIBAR_BIOS_CONTROL_BILD (1 << 7)
+#define SPIBAR_BIOS_CONTROL_EXT_BIOS_ENABLE (1 << 27)
+#define SPIBAR_BIOS_CONTROL_EXT_BIOS_LIMIT(x) ((x) & ~(0xfff))
/* Register offsets from the MMIO region base (PCI_BASE_ADDRESS_0) */
diff --git a/src/soc/intel/common/block/include/intelblocks/fast_spi.h b/src/soc/intel/common/block/include/intelblocks/fast_spi.h
index 0a7e64dad4..81437b6e6a 100644
--- a/src/soc/intel/common/block/include/intelblocks/fast_spi.h
+++ b/src/soc/intel/common/block/include/intelblocks/fast_spi.h
@@ -73,12 +73,15 @@ bool fast_spi_wpd_status(void);
* Enable SPI Write protect.
*/
void fast_spi_enable_wp(void);
-
/*
* Get base and size of extended BIOS decode window used at runtime in host address space. If
* the BIOS region is not greater than 16MiB, then this function returns 0 for both base and
* size.
*/
void fast_spi_get_ext_bios_window(uintptr_t *base, size_t *size);
+/*
+ * SOC function to get SPI-DMI Destination Id
+ */
+uint32_t soc_get_spi_dmi_destination_id(void);
#endif /* SOC_INTEL_COMMON_BLOCK_FAST_SPI_H */