summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/cpu/intel_common/Makefile1
-rw-r--r--arch/x86/cpu/intel_common/fast_spi.c73
-rw-r--r--arch/x86/include/asm/fast_spi.h68
-rw-r--r--arch/x86/include/asm/spl.h1
4 files changed, 143 insertions, 0 deletions
diff --git a/arch/x86/cpu/intel_common/Makefile b/arch/x86/cpu/intel_common/Makefile
index 07f27c29ec..dfbc29f047 100644
--- a/arch/x86/cpu/intel_common/Makefile
+++ b/arch/x86/cpu/intel_common/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += report_platform.o
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += mrc.o
endif
obj-y += cpu.o
+obj-y += fast_spi.o
obj-y += lpc.o
ifndef CONFIG_TARGET_EFI_APP
obj-$(CONFIG_$(SPL_TPL_)X86_32BIT_INIT) += microcode.o
diff --git a/arch/x86/cpu/intel_common/fast_spi.c b/arch/x86/cpu/intel_common/fast_spi.c
new file mode 100644
index 0000000000..a6e3d0a5bf
--- /dev/null
+++ b/arch/x86/cpu/intel_common/fast_spi.c
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2019 Google LLC
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/cpu_common.h>
+#include <asm/fast_spi.h>
+#include <asm/pci.h>
+
+/*
+ * Returns bios_start and fills in size of the BIOS region.
+ */
+static ulong fast_spi_get_bios_region(struct fast_spi_regs *regs,
+ uint *bios_size)
+{
+ ulong bios_start, bios_end;
+
+ /*
+ * BIOS_BFPREG provides info about BIOS-Flash Primary Region Base and
+ * Limit. Base and Limit fields are in units of 4K.
+ */
+ u32 val = readl(&regs->bfp);
+
+ bios_start = (val & SPIBAR_BFPREG_PRB_MASK) << 12;
+ bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >>
+ SPIBAR_BFPREG_PRL_SHIFT) + 1) << 12;
+ *bios_size = bios_end - bios_start;
+
+ return bios_start;
+}
+
+int fast_spi_get_bios_mmap(pci_dev_t pdev, ulong *map_basep, uint *map_sizep,
+ uint *offsetp)
+{
+ struct fast_spi_regs *regs;
+ ulong bar, base, mmio_base;
+
+ /* Special case to find mapping without probing the device */
+ pci_x86_read_config(pdev, PCI_BASE_ADDRESS_0, &bar, PCI_SIZE_32);
+ mmio_base = bar & PCI_BASE_ADDRESS_MEM_MASK;
+ regs = (struct fast_spi_regs *)mmio_base;
+ base = fast_spi_get_bios_region(regs, map_sizep);
+ *map_basep = (u32)-*map_sizep - base;
+ *offsetp = base;
+
+ return 0;
+}
+
+int fast_spi_early_init(pci_dev_t pdev, ulong mmio_base)
+{
+ /* Program Temporary BAR for SPI */
+ pci_x86_write_config(pdev, PCI_BASE_ADDRESS_0,
+ mmio_base | PCI_BASE_ADDRESS_SPACE_MEMORY,
+ PCI_SIZE_32);
+
+ /* Enable Bus Master and MMIO Space */
+ pci_x86_clrset_config(pdev, PCI_COMMAND, 0, PCI_COMMAND_MASTER |
+ PCI_COMMAND_MEMORY, PCI_SIZE_8);
+
+ /*
+ * Disable the BIOS write protect so write commands are allowed.
+ * Enable Prefetching and caching.
+ */
+ pci_x86_clrset_config(pdev, SPIBAR_BIOS_CONTROL,
+ SPIBAR_BIOS_CONTROL_EISS |
+ SPIBAR_BIOS_CONTROL_CACHE_DISABLE,
+ SPIBAR_BIOS_CONTROL_WPD |
+ SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE, PCI_SIZE_8);
+
+ return 0;
+}
diff --git a/arch/x86/include/asm/fast_spi.h b/arch/x86/include/asm/fast_spi.h
new file mode 100644
index 0000000000..6894298526
--- /dev/null
+++ b/arch/x86/include/asm/fast_spi.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2017 Intel Corporation.
+ */
+
+#ifndef ASM_FAST_SPI_H
+#define ASM_FAST_SPI_H
+
+/* Register offsets from the MMIO region base (PCI_BASE_ADDRESS_0) */
+struct fast_spi_regs {
+ u32 bfp;
+ u32 hsfsts_ctl;
+ u32 faddr;
+ u32 dlock;
+
+ u32 fdata[0x10];
+
+ u32 fracc;
+ u32 freg[12];
+ u32 fpr[5];
+ u32 gpr0;
+ u32 spare2;
+ u32 sts_ctl;
+ u16 preop;
+ u16 optype;
+ u8 opmenu[8];
+
+ u32 spare3;
+ u32 fdoc;
+ u32 fdod;
+ u32 spare4;
+ u32 afc;
+ u32 vscc[2];
+ u32 ptinx;
+ u32 ptdata;
+};
+check_member(fast_spi_regs, ptdata, 0xd0);
+
+/* Bit definitions for BFPREG (0x00) register */
+#define SPIBAR_BFPREG_PRB_MASK 0x7fff
+#define SPIBAR_BFPREG_PRL_SHIFT 16
+#define SPIBAR_BFPREG_PRL_MASK (0x7fff << SPIBAR_BFPREG_PRL_SHIFT)
+
+/* PCI configuration registers */
+#define SPIBAR_BIOS_CONTROL 0xdc
+#define SPIBAR_BIOS_CONTROL_WPD BIT(0)
+#define SPIBAR_BIOS_CONTROL_LOCK_ENABLE BIT(1)
+#define SPIBAR_BIOS_CONTROL_CACHE_DISABLE BIT(2)
+#define SPIBAR_BIOS_CONTROL_PREFETCH_ENABLE BIT(3)
+#define SPIBAR_BIOS_CONTROL_EISS BIT(5)
+#define SPIBAR_BIOS_CONTROL_BILD BIT(7)
+
+/**
+ * fast_spi_get_bios_mmap() - Get memory map for SPI flash
+ *
+ * @pdev: PCI device to use (this is the Fast SPI device)
+ * @map_basep: Returns base memory address for mapped SPI
+ * @map_sizep: Returns size of mapped SPI
+ * @offsetp: Returns start offset of SPI flash where the map works
+ * correctly (offsets before this are not visible)
+ * @return 0 (always)
+ */
+int fast_spi_get_bios_mmap(pci_dev_t pdev, ulong *map_basep, uint *map_sizep,
+ uint *offsetp);
+
+int fast_spi_early_init(pci_dev_t pdev, ulong mmio_base);
+
+#endif /* ASM_FAST_SPI_H */
diff --git a/arch/x86/include/asm/spl.h b/arch/x86/include/asm/spl.h
index 1bef4877eb..cc6cac08f2 100644
--- a/arch/x86/include/asm/spl.h
+++ b/arch/x86/include/asm/spl.h
@@ -11,6 +11,7 @@
enum {
BOOT_DEVICE_SPI_MMAP = 10,
+ BOOT_DEVICE_FAST_SPI,
BOOT_DEVICE_CROS_VBOOT,
};