soc/amd/common/block/lpc: Use ROM3 window if possible
On x86_64 use the ROM3 window to access the SPI flash. Use the
same mechanism as on Intel, where the lower 16Mbyte are mapped
using ROM2 window and the upper pages are mapped using the ROM3
window. By default the ROM3 window resides in high MMIO and thus
needs 1024GiB of the address space to be identity mapped in the
page tables.
This allows legacy 32-bit code to work on mappings in the lower
16MiB of the flash chip.
Introduces new messages in coreboot log:
[INFO ] ROM2 Decode Window: SPI flash base=0x0, Host base=0xff000000, Size=0x1000000
[INFO ] ROM3 Decode Window: SPI flash base=0x1000000, Host base=0xfd01000000, Size=0x3000000
TEST: Disabled ROM2 mapping and booted from ROM3 mapping in x86_64
on amd/birman+.
Change-Id: I8976273cfb31765d7f893b3fc137f117c63b6553
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Reviewed-on: https://review.coreboot.org/c/coreboot/+/86584
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Naresh <naresh.solanki.2011@gmail.com>
This commit is contained in:
parent
9d878fc6c0
commit
cbbf380fa4
4 changed files with 187 additions and 0 deletions
|
|
@ -16,11 +16,29 @@ config SOC_AMD_COMMON_BLOCK_SPI_4DW_BURST
|
|||
help
|
||||
Select this option to keep the 4 DWORD burst support enabled.
|
||||
|
||||
config SOC_AMD_COMMON_BLOCK_SPI_MMAP_USE_ROM3
|
||||
bool
|
||||
default y if ROM_SIZE > 0x01000000
|
||||
depends on !SOC_AMD_PICASSO && !SOC_AMD_STONEYRIDGE
|
||||
depends on !SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA
|
||||
depends on USE_X86_64_SUPPORT
|
||||
# Enable X86_CUSTOM_BOOTMEDIA because the fast SPI controller
|
||||
# driver provides a custom boot media device when multiple decode
|
||||
# windows are used for the BIOS region.
|
||||
select X86_CUSTOM_BOOTMEDIA
|
||||
help
|
||||
AMD specific SPI flash access. The lower 16MiB of the SPI flash are
|
||||
memory mapped on the ROM2 window and the upper SPI flash is mapped using
|
||||
the ROM3 window in high MMIO. The ROM3 window maps up to 64MiB of the
|
||||
SPI flash. The default address of ROM3 is below 1024GiB address boundary
|
||||
and thus can only be used in x86_64 mode.
|
||||
|
||||
config SOC_AMD_COMMON_BLOCK_SPI_MMAP
|
||||
def_bool y
|
||||
select X86_CUSTOM_BOOTMEDIA
|
||||
depends on SOC_AMD_COMMON_BLOCK_SPI
|
||||
depends on !SOC_AMD_COMMON_BLOCK_LPC_SPI_DMA
|
||||
depends on !SOC_AMD_COMMON_BLOCK_SPI_MMAP_USE_ROM3
|
||||
help
|
||||
This option is required when CONFIG_ROM_SIZE is greater than 16 MiB.
|
||||
This flash driver still only mmaps 16 MiB of the flash (depending
|
||||
|
|
|
|||
|
|
@ -4,6 +4,9 @@ ifeq ($(CONFIG_SOC_AMD_COMMON_BLOCK_SPI),y)
|
|||
all_x86-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MMAP) += mmap_boot.c
|
||||
smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MMAP) += mmap_boot.c
|
||||
|
||||
all-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MMAP_USE_ROM3) += mmap_boot_rom3.c
|
||||
smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_SPI_MMAP_USE_ROM3) += mmap_boot_rom3.c
|
||||
|
||||
bootblock-y += fch_spi_ctrl.c
|
||||
romstage-y += fch_spi_ctrl.c
|
||||
verstage-y += fch_spi_ctrl.c
|
||||
|
|
|
|||
163
src/soc/amd/common/block/spi/mmap_boot_rom3.c
Normal file
163
src/soc/amd/common/block/spi/mmap_boot_rom3.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <boot_device.h>
|
||||
#include <spi_flash.h>
|
||||
#include <stdint.h>
|
||||
#include <amdblocks/lpc.h>
|
||||
|
||||
enum window_type {
|
||||
/* Fixed decode window of max 16MiB size just below 4G boundary */
|
||||
ROM2_DECODE_WINDOW,
|
||||
/* Additional decode window for mapping BIOS region greater than 16MiB */
|
||||
ROM3_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 initialize_window(const size_t win_idx, const enum window_type type,
|
||||
uintptr_t host_base, uintptr_t flash_base, size_t size)
|
||||
{
|
||||
mem_region_device_ro_init(&shadow_devs[win_idx], (void *)host_base, size);
|
||||
xlate_window_init(&real_dev_windows[win_idx], &shadow_devs[win_idx].rdev,
|
||||
flash_base, size);
|
||||
printk(BIOS_INFO, "ROM%d Decode Window: ",
|
||||
(type == ROM2_DECODE_WINDOW) ? 2 : 3);
|
||||
printk(BIOS_INFO, "SPI flash base=0x%lx, Host base=0x%lx, Size=0x%zx\n",
|
||||
flash_base, host_base, size);
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Note: This configuration assumes no flash remapping (fch_spi_rom_remapping() = 0).
|
||||
*
|
||||
* +--------------+
|
||||
* | |
|
||||
* | |
|
||||
* | |
|
||||
* CONFIG_ROM_SIZE +------------+--------------------------+--------------------------------+- rom3_end
|
||||
* | | ^ | |
|
||||
* | | | | ROM3 |
|
||||
* | | | | |
|
||||
* | | | | |
|
||||
* | | + | |
|
||||
* | | rom3_size | |
|
||||
* | | + | |
|
||||
* | SPI ROM | | | |
|
||||
* | | +----+-----------------+--------------+
|
||||
* | | | | | |
|
||||
* | | | | | |
|
||||
* | | | V | |
|
||||
* | | | +---0xfd00000000--+--------------+- rom3_start
|
||||
* | | | | |
|
||||
* | | | | |
|
||||
* | | | | Other MMIO |
|
||||
* | | | | |
|
||||
* +------------+ --------------------+---------0x100000000--+--------------+- rom2_end
|
||||
* | | ^ | |
|
||||
* | | | | |
|
||||
* | | rom2_size | ROM2 |
|
||||
* | | | | |
|
||||
* | | V | |
|
||||
* 0 +------------+ ------------------------------0xFF0000000--+--------------+- rom2_start
|
||||
* | |
|
||||
* SPI flash | |
|
||||
* address | |
|
||||
* space | |
|
||||
* +--------------+
|
||||
*
|
||||
* Host address
|
||||
* space
|
||||
*/
|
||||
static void bios_mmap_init(void)
|
||||
{
|
||||
static bool init_done;
|
||||
size_t win_count = 0;
|
||||
size_t map_win_size = 0;
|
||||
|
||||
if (init_done)
|
||||
return;
|
||||
|
||||
/*
|
||||
* By default, fixed decode window (maximum size 16MiB) is mapped just
|
||||
* below the 4G boundary. This window maps the bottom part of the BIOS
|
||||
* region in the SPI flash address space to the host address space.
|
||||
*/
|
||||
size_t rom2_size = 0;
|
||||
const uintptr_t rom2_start = lpc_get_rom2_region(&rom2_size);
|
||||
if (rom2_start && rom2_size) {
|
||||
initialize_window(win_count, ROM2_DECODE_WINDOW, rom2_start, 0, rom2_size);
|
||||
win_count++;
|
||||
map_win_size += rom2_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remaining portion of the BIOS region up to a maximum of 64MiB is
|
||||
* mapped at the bottom of the ROM3 if the BIOS region is greater than 16MiB.
|
||||
* The ROM3 window is only used when it's inside the identity mapped
|
||||
* page tables used by x86_64.
|
||||
*
|
||||
* If the BIOS region is not greater than 16MiB, then the ROM3 window is not
|
||||
* enabled.
|
||||
*/
|
||||
size_t rom3_size;
|
||||
const uint64_t rom3_start = lpc_get_rom3_region(&rom3_size);
|
||||
const uint64_t rom3_end = rom3_start + rom3_size;
|
||||
|
||||
if (CONFIG_ROM_SIZE > 16 * MiB) {
|
||||
assert(rom3_start);
|
||||
assert(rom3_size > 16 * MiB);
|
||||
assert(DIV_ROUND_UP(rom3_end, GiB) < CONFIG_CPU_PT_ROM_MAP_GB);
|
||||
}
|
||||
|
||||
if (CONFIG_ROM_SIZE > 16 * MiB &&
|
||||
rom3_start > 0 &&
|
||||
rom3_size > 16 * MiB &&
|
||||
DIV_ROUND_UP(rom3_end, GiB) < CONFIG_CPU_PT_ROM_MAP_GB) {
|
||||
|
||||
const size_t ext_win_size = MIN(rom3_size, CONFIG_ROM_SIZE - rom2_size);
|
||||
|
||||
initialize_window(win_count, ROM3_DECODE_WINDOW,
|
||||
rom3_start + rom2_size, rom2_size, ext_win_size);
|
||||
win_count++;
|
||||
map_win_size += ext_win_size;
|
||||
}
|
||||
|
||||
assert(map_win_size == CONFIG_ROM_SIZE);
|
||||
xlate_region_device_ro_init(&real_dev, win_count, real_dev_windows, map_win_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);
|
||||
/* FIXME: Allow SPI mmap in 64-bit address space */
|
||||
if ((uintptr_t)rdev_mmap_full(&shadow_devs[i].rdev) < 4ULL * GiB)
|
||||
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;
|
||||
}
|
||||
|
|
@ -101,6 +101,9 @@ config CHIPSET_DEVICETREE
|
|||
string
|
||||
default "soc/amd/glinda/chipset.cb"
|
||||
|
||||
config CPU_PT_ROM_MAP_GB
|
||||
default 1024
|
||||
|
||||
config EARLY_RESERVED_DRAM_BASE
|
||||
hex
|
||||
default 0x2000000
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue