On Mon, Oct 21, 2019 at 11:33 AM Simon Glass <s...@chromium.org> wrote: > > Most x86 CPUs use a mechanism where the SPI flash is mapped into the very > top of 32-bit address space, so that it can be executed in place and read > simply by copying from memory. For an 8MB ROM the mapping starts at > 0xff800000. > > However some recent Intel CPUs do not use a simple 1:1 memory map. Instead > the map starts at a different address and not all of the SPI flash is > accessible through the map. This 'Fast SPI' feature requires that U-Boot > check the location of the map. It is also possible (optionally) to read > from the SPI flash using a driver. > > Add support for booting from Fast SPI. The memory-mapped version is used > by both TPL and SPL on apollolake. > > In respect of a SPI flash driver, the actual SPI driver is ich.c - this > just adds a few helper functions and definitions. > > This is used by Apollolake. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > Changes in v3: > - Add support for of-platdata for TPL > - Add the missing header file > - Change Fast-SPI driver into a helper file used by ICH SPI > - Don't include write() and erase() in TPL > - Merge in patch "x86: Add support for booting from Fast SPI" > - Reorder file so that write() and erase() are together > - Use pci_get_devfn() > > Changes in v2: None > > arch/x86/cpu/intel_common/Makefile | 1 + > arch/x86/cpu/intel_common/fast_spi.c | 73 ++++++++++++++++++++++++++++ > arch/x86/include/asm/fast_spi.h | 68 ++++++++++++++++++++++++++ > arch/x86/include/asm/spl.h | 1 + > 4 files changed, 143 insertions(+) > create mode 100644 arch/x86/cpu/intel_common/fast_spi.c > create mode 100644 arch/x86/include/asm/fast_spi.h > > diff --git a/arch/x86/cpu/intel_common/Makefile > b/arch/x86/cpu/intel_common/Makefile > index 07f27c29ec7..dfbc29f0475 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 00000000000..a6e3d0a5bfc > --- /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(®s->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 00000000000..6c1bda2184f > --- /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; /* a4 */
I assume a4 is the offset of preop? Leaving it causes confusion and it can be dropped, I think. > + 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 1bef4877eb3..cc6cac08f23 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, > }; > > -- Regards, Bin _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de https://lists.denx.de/listinfo/u-boot