summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/soc/intel/apollolake/Makefile.inc1
-rw-r--r--src/soc/intel/apollolake/bootblock/bootblock.c32
-rw-r--r--src/soc/intel/apollolake/chip.c14
-rw-r--r--src/soc/intel/apollolake/include/soc/iomap.h3
4 files changed, 50 insertions, 0 deletions
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 <soc/northbridge.h>
#include <soc/pci_devs.h>
#include <soc/uart.h>
+#include <spi-generic.h>
#include <timestamp.h>
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 <soc/intel/common/vbt.h>
#include <soc/nvs.h>
#include <soc/pci_devs.h>
+#include <spi-generic.h>
#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_ */