Attention is currently required from: Jason Glenesk, Raul Rangel, Matt DeVillier, Zheng Bao, Fred Reitberger, Felix Held.
Hello Zheng Bao,
I'd like you to do a code review. Please visit
https://review.coreboot.org/c/coreboot/+/74260
to review the following change.
Change subject: WIP: Add xlate_windows to mmap 32M flash ......................................................................
WIP: Add xlate_windows to mmap 32M flash
Use SPI ROM page to switch pages.
This is one of series of patches to support 32/64M flash. BUG=b:255374782
Change-Id: Ibd2bf1390635494443cac9ee8600a4a741a78c0d Signed-off-by: Zheng Bao fishbaozi@gmail.com --- M src/soc/amd/common/block/spi/Kconfig M src/soc/amd/common/block/spi/Makefile.inc A src/soc/amd/common/block/spi/spi_map_big.c 3 files changed, 236 insertions(+), 0 deletions(-)
git pull ssh://review.coreboot.org:29418/coreboot refs/changes/60/74260/1
diff --git a/src/soc/amd/common/block/spi/Kconfig b/src/soc/amd/common/block/spi/Kconfig index 7a300e4..85a60fc 100644 --- a/src/soc/amd/common/block/spi/Kconfig +++ b/src/soc/amd/common/block/spi/Kconfig @@ -100,3 +100,10 @@ 3: 16.66MHz 4: 100MHz 5: 800KHz + +config SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG + bool + select X86_CUSTOM_BOOTMEDIA + depends on !SOC_AMD_PICASSO && !SOC_AMD_STONEYRIDGE + help + Select this option to enable SPI more than 16M bytes. diff --git a/src/soc/amd/common/block/spi/Makefile.inc b/src/soc/amd/common/block/spi/Makefile.inc index 55ca308..37d7169 100644 --- a/src/soc/amd/common/block/spi/Makefile.inc +++ b/src/soc/amd/common/block/spi/Makefile.inc @@ -22,4 +22,11 @@ verstage-y += fch_spi_util.c smm-$(CONFIG_SPI_FLASH_SMM) += fch_spi_util.c
+bootblock-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG) += spi_map_big.c +romstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG) += spi_map_big.c +postcar-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG) += spi_map_big.c +ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG) += spi_map_big.c +verstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG) += spi_map_big.c +smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MAP_BIG) += spi_map_big.c + endif # CONFIG_SOC_AMD_COMMON_BLOCK_SPI diff --git a/src/soc/amd/common/block/spi/spi_map_big.c b/src/soc/amd/common/block/spi/spi_map_big.c new file mode 100644 index 0000000..8d8e0c1 --- /dev/null +++ b/src/soc/amd/common/block/spi/spi_map_big.c @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* + * This file provides a custom boot media device for the platforms that support additional + * window for BIOS regions greater than 16MiB. If the mainboard uses a smaller BIOS region, then + * the additional window is unused. + */ + +#include <boot_device.h> +#include <commonlib/region.h> +#include <console/console.h> +#include <fmap.h> +#include <string.h> +#include <spi_flash.h> +#include <amdblocks/spi.h> + +#define rom_base ((void *)(uintptr_t)(0x100000000ULL-0x1000000)) + +enum window_type { + /* Fixed decode window of max 16MiB size just below 4G boundary */ + FIXED_DECODE_WINDOW, + /* Additional decode window for mapping BIOS region greater than 16MiB */ + EXT_BIOS_DECODE_WINDOW, + TOTAL_DECODE_WINDOWS, +}; + +static struct xlate_region_device real_dev; +static struct mem_region_device shadow_devs[TOTAL_DECODE_WINDOWS]; +static struct xlate_window real_dev_windows[TOTAL_DECODE_WINDOWS]; + +static void *spi_amd_mmap(const struct region_device *rd, size_t offset, + size_t size) +{ + const struct mem_region_device *mdev; + + spi_write32(SPI_ROM_PAGE, 0); + + mdev = container_of(rd, __typeof__(*mdev), rdev); + return &mdev->base[offset]; +} + +static void *spi_amd_mmap_p1(const struct region_device *rd, size_t offset, + size_t size) +{ + const struct mem_region_device *mdev; + + spi_write32(SPI_ROM_PAGE, 1); + + mdev = container_of(rd, __typeof__(*mdev), rdev); + return &mdev->base[offset]; +} + +static int spi_amd_munmap(const struct region_device *rd __always_unused, + void *mapping __always_unused) +{ + /* The FSP takes the assumption that the ROM page is 0. */ + spi_write32(SPI_ROM_PAGE, 0); + + return 0; +} + +static ssize_t spi_amd_readat(const struct region_device *rd, void *b, size_t offset, + size_t size) +{ + const struct mem_region_device *mdev; + + spi_write32(SPI_ROM_PAGE, 0); + + mdev = container_of(rd, __typeof__(*mdev), rdev); + memcpy(b, &mdev->base[offset], size); + + return size; +} + +static ssize_t spi_amd_readat_p1(const struct region_device *rd, void *b, size_t offset, + size_t size) +{ + const struct mem_region_device *mdev; + + spi_write32(SPI_ROM_PAGE, 1); + + mdev = container_of(rd, __typeof__(*mdev), rdev); + memcpy(b, &mdev->base[offset], size); + + spi_write32(SPI_ROM_PAGE, 0); + return size; +} + +const struct region_device_ops spi_amd_rdev_ro_ops = { + .mmap = spi_amd_mmap, + .munmap = spi_amd_munmap, + .readat = spi_amd_readat, +}; + +const struct region_device_ops spi_amd_rdev_ro_ops_p1 = { + .mmap = spi_amd_mmap_p1, + .munmap = spi_amd_munmap, + .readat = spi_amd_readat_p1, +}; + +static const struct mem_region_device boot_dev_top = { + .base = rom_base, + .rdev = REGION_DEV_INIT(&spi_amd_rdev_ro_ops_p1, 0, 0x1000000), +}; + +static const struct mem_region_device boot_dev_bottom = { + .base = rom_base, + .rdev = REGION_DEV_INIT(&spi_amd_rdev_ro_ops, 0, 0x1000000), +}; + +static void initialize_window_top(enum window_type type, uintptr_t host_base, + uintptr_t flash_base, size_t size) +{ + xlate_window_init(&real_dev_windows[type], &boot_dev_top.rdev, + flash_base, size); +} + +static void initialize_window_bottom(enum window_type type, uintptr_t host_base, + uintptr_t flash_base, size_t size) +{ + xlate_window_init(&real_dev_windows[type], &boot_dev_bottom.rdev, + flash_base, size); +} + +static void bios_mmap_init(void) +{ + static bool init_done = false; + + uintptr_t fixed_win_host_base, fixed_win_flash_base; + uintptr_t ext_win_host_base, ext_win_flash_base; + size_t fixed_win_size, ext_win_size; + + size_t win_count = 0; + + if (init_done) + return; + + /* Read the offset and size of BIOS region in the SPI flash address space. */ + //bios_start = fast_spi_get_bios_region(&bios_size); + + /* + * By default, fixed decode window (maximum size 16MiB) is mapped just below the 4G + * boundary. This window maps the top part of the BIOS region in the SPI flash address + * space to the host address space. + */ + fixed_win_size = 16 * MiB; + fixed_win_host_base = 4ULL * GiB - fixed_win_size; + fixed_win_flash_base = 0x0; + printk(BIOS_DEBUG, "bios_mmap_init: 2\n"); + + initialize_window_bottom(FIXED_DECODE_WINDOW, fixed_win_host_base, fixed_win_flash_base, fixed_win_size); + win_count++; + + //_Static_assert(CONFIG_EXT_BIOS_WIN_BASE != 0, "Extended BIOS window base cannot be 0!"); + //_Static_assert(CONFIG_EXT_BIOS_WIN_SIZE != 0, "Extended BIOS window size cannot be 0!"); + + /* + * Remaining portion of the BIOS region up to a maximum of CONFIG_EXT_BIOS_WIN_SIZE is + * mapped at the top of the extended window if the BIOS region is greater than 16MiB. + * + * If the BIOS region is not greater than 16MiB, then the extended window is not + * enabled. + */ + ext_win_size = 16 * MiB; + + if (ext_win_size) { + ext_win_host_base = 0xff000000; + ext_win_flash_base = 0x1000000; + initialize_window_top(EXT_BIOS_DECODE_WINDOW, ext_win_host_base, + ext_win_flash_base, ext_win_size); + win_count++; + } + + xlate_region_device_ro_init(&real_dev, win_count, real_dev_windows, CONFIG_ROM_SIZE); + + init_done = true; +} + +const struct region_device *boot_device_ro(void) +{ + bios_mmap_init(); + + return &real_dev.rdev; +} + +uint32_t spi_flash_get_mmap_windows(struct flash_mmap_window *table) +{ + int i; + uint32_t count = 0; + + bios_mmap_init(); + + for (i = 0; i < TOTAL_DECODE_WINDOWS; i++) { + + if (region_sz(&real_dev_windows[i].sub_region) == 0) + continue; + + count++; + table->flash_base = region_offset(&real_dev_windows[i].sub_region); + table->host_base = (uintptr_t)rdev_mmap_full(&shadow_devs[i].rdev); + table->size = region_sz(&real_dev_windows[i].sub_region); + + table++; + } + + return count; +}