diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc index 38ed07deb6..a840ad5a15 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -15,6 +15,7 @@ bootblock-y += car.c bootblock-y += gpio.c bootblock-y += lpc_lib.c bootblock-y += mmap_boot.c +bootblock-y += spi.c bootblock-y += tsc_freq.c bootblock-$(CONFIG_SOC_UART_DEBUG) += uart_early.c diff --git a/src/soc/intel/apollolake/bootblock/bootblock.c b/src/soc/intel/apollolake/bootblock/bootblock.c index ca402e922b..deec368129 100644 --- a/src/soc/intel/apollolake/bootblock/bootblock.c +++ b/src/soc/intel/apollolake/bootblock/bootblock.c @@ -25,6 +25,7 @@ #include #include #include +#include #include static const struct pad_config tpm_spi_configs[] = { @@ -101,6 +102,35 @@ static void cache_bios_region(void) set_var_mtrr(mtrr, 4ULL*GiB - rom_size, rom_size, MTRR_TYPE_WRPROT); } +/* + * Program temporary BAR for SPI in case any of the stages before ramstage need + * to access SPI MMIO regs. Ramstage will assign a new BAR during PCI + * enumeration. + */ +static void enable_spibar(void) +{ + device_t dev = SPI_DEV; + uint8_t val; + + /* Disable Bus Master and MMIO space. */ + val = pci_read_config8(dev, PCI_COMMAND); + val &= ~(PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY); + pci_write_config8(dev, PCI_COMMAND, val); + + /* Program Temporary BAR for SPI */ + pci_write_config32(dev, PCI_BASE_ADDRESS_0, + PRERAM_SPI_BASE_ADDRESS | + PCI_BASE_ADDRESS_SPACE_MEMORY); + + /* Enable Bus Master and MMIO Space */ + val = pci_read_config8(dev, PCI_COMMAND); + val |= PCI_COMMAND_MASTER | PCI_COMMAND_MEMORY; + pci_write_config8(dev, PCI_COMMAND, val); + + /* Initialize SPI to allow BIOS to write/erase on flash. */ + spi_init(); +} + void bootblock_soc_early_init(void) { /* Prepare UART for serial console. */ @@ -112,5 +142,7 @@ void bootblock_soc_early_init(void) enable_pm_timer(); + enable_spibar(); + cache_bios_region(); } diff --git a/src/soc/intel/apollolake/chip.c b/src/soc/intel/apollolake/chip.c index 94a101f501..4fa4ce4b6d 100644 --- a/src/soc/intel/apollolake/chip.c +++ b/src/soc/intel/apollolake/chip.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "chip.h" @@ -164,3 +165,16 @@ BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_LOAD, BS_ON_EXIT, fsp_notify_dummy, (void *) READY_TO_BOOT); BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, fsp_notify_dummy, (void *) READY_TO_BOOT); + +/* + * spi_init() needs to run unconditionally on every boot (including resume) to + * allow write protect to be disabled for eventlog and nvram updates. This needs + * to be done as early as possible in ramstage. Thus, add a callback for entry + * into BS_PRE_DEVICE. + */ +static void spi_init_cb(void *unused) +{ + spi_init(); +} + +BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, spi_init_cb, NULL); diff --git a/src/soc/intel/apollolake/include/soc/iomap.h b/src/soc/intel/apollolake/include/soc/iomap.h index e676ba5a7f..716c2a604f 100644 --- a/src/soc/intel/apollolake/include/soc/iomap.h +++ b/src/soc/intel/apollolake/include/soc/iomap.h @@ -30,4 +30,7 @@ #define PMC_BAR0 0xfe042000 #define PMC_BAR1 0xfe044000 +/* Temporary BAR for SPI until PCI enumeration assigns a BAR in ramstage. */ +#define PRERAM_SPI_BASE_ADDRESS 0xfe010000 + #endif /* _SOC_APOLLOLAKE_IOMAP_H_ */