diff options
-rw-r--r-- | src/soc/intel/common/block/fast_spi/fast_spi.c | 64 | ||||
-rw-r--r-- | src/soc/intel/common/block/fast_spi/fast_spi_def.h | 5 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/fast_spi.h | 5 |
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 */ |