From 0be3da53c6eb1b4c05a51151c8059fbb4d4024ac Mon Sep 17 00:00:00 2001 From: Furquan Shaikh Date: Sun, 19 Jun 2016 23:20:43 -0700 Subject: intel/apollolake: Calculate BIOS mmap at runtime Instead of hard-coding the BIOS region start and end addresses, read BIOS_BFPREG to determine the base and limit for the mapped BIOS region. BUG=chrome-os-partner:54563 Change-Id: Iddd3d4cc945f09e8f147e293bb9144471a6a220d Signed-off-by: Furquan Shaikh Reviewed-on: https://review.coreboot.org/15269 Reviewed-by: Aaron Durbin Tested-by: build bot (Jenkins) --- src/soc/intel/apollolake/Makefile.inc | 3 + src/soc/intel/apollolake/include/soc/spi.h | 7 ++ src/soc/intel/apollolake/mmap_boot.c | 132 +++++++++++++++++++++++------ 3 files changed, 117 insertions(+), 25 deletions(-) diff --git a/src/soc/intel/apollolake/Makefile.inc b/src/soc/intel/apollolake/Makefile.inc index a7596e43fe..7d49b066fe 100644 --- a/src/soc/intel/apollolake/Makefile.inc +++ b/src/soc/intel/apollolake/Makefile.inc @@ -56,11 +56,13 @@ ramstage-y += tsc_freq.c ramstage-y += pmutil.c ramstage-y += pmc.c ramstage-y += smi.c +ramstage-y += spi.c ramstage-y += reset.c postcar-y += exit_car.S postcar-y += memmap.c postcar-y += mmap_boot.c +postcar-y += spi.c postcar-$(CONFIG_SOC_UART_DEBUG) += uart_early.c postcar-y += tsc_freq.c @@ -71,6 +73,7 @@ verstage-$(CONFIG_SOC_UART_DEBUG) += uart_early.c verstage-y += tsc_freq.c verstage-y += pmutil.c verstage-y += reset.c +verstage-y += spi.c CPPFLAGS_common += -I$(src)/soc/intel/apollolake/include diff --git a/src/soc/intel/apollolake/include/soc/spi.h b/src/soc/intel/apollolake/include/soc/spi.h index f67110f125..20e78d7843 100644 --- a/src/soc/intel/apollolake/include/soc/spi.h +++ b/src/soc/intel/apollolake/include/soc/spi.h @@ -28,12 +28,19 @@ #define SPIBAR_BIOS_CONTROL_EISS (1 << 5) /* Register offsets from the MMIO region base (PCI_BASE_ADDRESS_0) */ +#define SPIBAR_BIOS_BFPREG 0x00 #define SPIBAR_HSFSTS_CTL 0x04 #define SPIBAR_FADDR 0x08 #define SPIBAR_FDATA(n) (0x10 + ((n) & 0xf) * 4) #define SPIBAR_PTINX 0xcc #define SPIBAR_PTDATA 0xd0 +/* Bit definitions and masks for BIOS_BFPREG register. */ +#define SPIBAR_BFPREG_PRB_MASK (0x7fff) +#define SPIBAR_BFPREG_PRL_SHIFT (16) +#define SPIBAR_BFPREG_PRL_MASK (0x7fff << SPIBAR_BFPREG_PRL_SHIFT) +#define SPIBAR_BFPREG_SBRS (1 << 31) + /* Bit definitions for HSFSTS_CTL register */ #define SPIBAR_HSFSTS_FBDC_MASK (0x3f << 24) #define SPIBAR_HSFSTS_FBDC(n) (((n) << 24) & SPIBAR_HSFSTS_FBDC_MASK) diff --git a/src/soc/intel/apollolake/mmap_boot.c b/src/soc/intel/apollolake/mmap_boot.c index e58723c812..d3c39ec393 100644 --- a/src/soc/intel/apollolake/mmap_boot.c +++ b/src/soc/intel/apollolake/mmap_boot.c @@ -16,42 +16,115 @@ * GNU General Public License for more details. */ +#include #include #include #include #include #include #include - -/* The 256 KiB right below 4G are decoded by readonly SRAM, not boot media */ -#define IFD_BIOS_MAX_MAPPED (CONFIG_IFD_BIOS_END - 256 * KiB) -#define IFD_MAPPED_SIZE (IFD_BIOS_MAX_MAPPED - CONFIG_IFD_BIOS_START) -#define IFD_BIOS_SIZE (CONFIG_IFD_BIOS_END - CONFIG_IFD_BIOS_START) +#include /* - * If Apollo Lake is configured to boot from SPI flash "BIOS" region - * (as defined in descriptor) is mapped below 4GiB. Form a pointer for - * the base. + * BIOS region on the flash is mapped right below 4GiB in the address + * space. However, 256KiB right below 4GiB is decoded by read-only SRAM and not + * boot media. + * + * +----------------+ 0 + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * | | + * +------------+ | | + * | IFD | | | + * bios_start +---> +------------+--------------------------> +----------------+ 4GiB - bios_size + * ^ | | ^ | | + * | | | | | | + * | | | bios_mapped_size | BIOS | + * | | BIOS | | | | + * bios_size | | | | | + * | | | v | | + * | | +--------------------------> +----------------+ 4GiB - 256KiB + * v | | | Read only SRAM | + * bios_end +---> +------------+ +----------------+ 4GiB + * | Device ext | + * +------------+ + * */ -#define VIRTUAL_ROM_BASE ((uintptr_t)(0x100000000ULL - IFD_BIOS_SIZE)) -static const struct mem_region_device shadow_dev = MEM_REGION_DEV_INIT( - VIRTUAL_ROM_BASE, IFD_BIOS_MAX_MAPPED -); +static size_t bios_start CAR_GLOBAL; +static size_t bios_size CAR_GLOBAL; -/* - * This is how we translate physical SPI flash address space into CPU memory-mapped space. In - * essence this means "BIOS" region (usually starts at flash physical 0x1000 is mapped to - * 4G - IFD_BIOS_SIZE. - */ -static const struct xlate_region_device real_dev = XLATE_REGION_DEV_INIT( - &shadow_dev.rdev, CONFIG_IFD_BIOS_START, - IFD_MAPPED_SIZE, CONFIG_ROM_SIZE -); +static struct mem_region_device shadow_dev CAR_GLOBAL; +static struct xlate_region_device real_dev CAR_GLOBAL; + +static void bios_mmap_init(void) +{ + size_t size; + + size = car_get_var(bios_size); + + /* If bios_size is initialized, then bail out. */ + if (size != 0) + return; + + size_t start, bios_end, bios_mapped_size; + uintptr_t base; + + /* + * BIOS_BFPREG provides info about BIOS Flash Primary Region + * Base and Limit. + * Base and Limit fields are in units of 4KiB. + */ + uint32_t val = spi_ctrlr_reg_read(SPIBAR_BIOS_BFPREG); + + start = (val & SPIBAR_BFPREG_PRB_MASK) * 4 * KiB; + bios_end = (((val & SPIBAR_BFPREG_PRL_MASK) >> + SPIBAR_BFPREG_PRL_SHIFT) + 1) * 4 * KiB; + size = bios_end - start; + + printk(BIOS_INFO, "IFD BIOS region info loaded from FLREG%d\n", + (val & SPIBAR_BFPREG_SBRS) ? 6 : 1); + printk(BIOS_INFO, "IFD BIOS Start: 0x%zx\n", start); + printk(BIOS_INFO, "IFD BIOS End : 0x%zx\n", bios_end); + + /* BIOS region is mapped right below 4G. */ + base = 4ULL * GiB - size; + + /* + * The 256 KiB right below 4G are decoded by readonly SRAM, + * not boot media. + */ + bios_mapped_size = size - 256 * KiB; + + struct mem_region_device *shadow_dev_ptr; + struct xlate_region_device *real_dev_ptr; + shadow_dev_ptr = car_get_var_ptr(&shadow_dev); + real_dev_ptr = car_get_var_ptr(&real_dev); + + mem_region_device_init(shadow_dev_ptr, (void *)base, + bios_mapped_size); + + xlate_region_device_init(real_dev_ptr, &shadow_dev_ptr->rdev, + start, bios_mapped_size, + CONFIG_ROM_SIZE); + + car_set_var(bios_start, start); + car_set_var(bios_size, size); +} const struct region_device *boot_device_ro(void) { - return &real_dev.rdev; + bios_mmap_init(); + + struct xlate_region_device *real_dev_ptr; + real_dev_ptr = car_get_var_ptr(&real_dev); + + return &real_dev_ptr->rdev; } static int iafw_boot_region_properties(struct cbfs_props *props) @@ -81,7 +154,16 @@ const struct cbfs_locator cbfs_master_header_locator = { uint32_t nvm_mmio_to_flash_offset(void *p) { - uintptr_t xlate_base; - xlate_base = VIRTUAL_ROM_BASE; - return (uintptr_t)p - xlate_base + CONFIG_IFD_BIOS_START; + bios_mmap_init(); + + size_t start, size; + start = car_get_var(bios_start); + size = car_get_var(bios_size); + + /* + * Returns : + * addr - base of mmaped region in addr space + offset of mmaped region + * start on flash + */ + return (uintptr_t)p - (4ULL * GiB - size) + start; } -- cgit v1.2.3