Only 16 MByte of the SPI flash can be mapped right below the 4 GB boundary. In case of a larger SPI flash size, still only the 16 MByte region starting at 0xff000000 can be configured as WRPROT and be reserved for the MMIO mapped SPI flash region. The next 16 MByte MMIO region starting at address 0xfe000000 contain for example the LAPIC MMIO region, the ACPIMMIO region and the UART/I2C controller MMIO regions which shouldn't be configured as WRPROT. Reserving this region for the MMIO mapped SPI flash would also result in an overlap with the MMIO resources mentioned above. In the case of a smaller SPI flash, reserving the full 16 MByte flash MMIO region makes sure that the resource allocator won't try to put anything else in the lower parts of the 16 MByte SPI mapping region. To avoid the issues described above, always reserve/cache the maximum amount of 16 MBytes of flash that can be mapped below 4 GB. TEST=On boards with 16 MByte SPI flash chips, the resulting image of a timeless build doesn't change with this patch. Verified this on Chausie (Mendocino), Majolica (Cezanne), Cereme (Picasso) and Google/Careena (Stoneyridge). On Mandolin (Picasso) with an 8 MByte flash, the resulting image of a timeless build is different, but neither the coreboot console output nor the Linux dmesg output shows any errors that might be related to this change. Signed-off-by: Felix Held <felix-coreboot@felixheld.de> Change-Id: Ie12bd48e48e267a84dc494f67e8e0c7a4a01a320 Reviewed-on: https://review.coreboot.org/c/coreboot/+/66700 Reviewed-by: Martin Roth <martin.roth@amd.corp-partner.google.com> Reviewed-by: Raul Rangel <rrangel@chromium.org> Reviewed-by: Fred Reitberger <reitbergerfred@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
94 lines
2.6 KiB
C
94 lines
2.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
#include <stdint.h>
|
|
#include <assert.h>
|
|
#include <console/console.h>
|
|
#include <cpu/x86/msr.h>
|
|
#include <cpu/amd/msr.h>
|
|
#include <cpu/x86/mtrr.h>
|
|
#include <smp/node.h>
|
|
#include <bootblock_common.h>
|
|
#include <amdblocks/agesawrapper.h>
|
|
#include <amdblocks/agesawrapper_call.h>
|
|
#include <amdblocks/amd_pci_mmconf.h>
|
|
#include <amdblocks/biosram.h>
|
|
#include <amdblocks/iomap.h>
|
|
#include <soc/pci_devs.h>
|
|
#include <soc/cpu.h>
|
|
#include <soc/southbridge.h>
|
|
#include <timestamp.h>
|
|
#include <halt.h>
|
|
|
|
#if CONFIG_PI_AGESA_TEMP_RAM_BASE < 0x100000
|
|
#error "Error: CONFIG_PI_AGESA_TEMP_RAM_BASE must be >= 1MB"
|
|
#endif
|
|
#if CONFIG_PI_AGESA_CAR_HEAP_BASE < 0x100000
|
|
#error "Error: CONFIG_PI_AGESA_CAR_HEAP_BASE must be >= 1MB"
|
|
#endif
|
|
|
|
/* Set the MMIO Configuration Base Address, Bus Range, and misc MTRRs. */
|
|
static void amd_initmmio(void)
|
|
{
|
|
msr_t mtrr_cap = rdmsr(MTRR_CAP_MSR);
|
|
int mtrr;
|
|
|
|
/*
|
|
* todo: AGESA currently writes variable MTRRs. Once that is
|
|
* corrected, un-hardcode this MTRR.
|
|
*
|
|
* Be careful not to use get_free_var_mtrr/set_var_mtrr pairs
|
|
* where all cores execute the path. Both cores within a compute
|
|
* unit share MTRRs. Programming core0 has the appearance of
|
|
* modifying core1 too. Using the pair again will create
|
|
* duplicate copies.
|
|
*/
|
|
mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_FLASH;
|
|
set_var_mtrr(mtrr, FLASH_BELOW_4GB_MAPPING_REGION_BASE,
|
|
FLASH_BELOW_4GB_MAPPING_REGION_SIZE, MTRR_TYPE_WRPROT);
|
|
|
|
mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_CAR_HEAP;
|
|
set_var_mtrr(mtrr, CONFIG_PI_AGESA_CAR_HEAP_BASE,
|
|
CONFIG_PI_AGESA_HEAP_SIZE, MTRR_TYPE_WRBACK);
|
|
|
|
mtrr = (mtrr_cap.lo & MTRR_CAP_VCNT) - SOC_EARLY_VMTRR_TEMPRAM;
|
|
set_var_mtrr(mtrr, CONFIG_PI_AGESA_TEMP_RAM_BASE,
|
|
CONFIG_PI_AGESA_HEAP_SIZE, MTRR_TYPE_UNCACHEABLE);
|
|
}
|
|
|
|
asmlinkage void bootblock_c_entry(uint64_t base_timestamp)
|
|
{
|
|
enable_pci_mmconf();
|
|
amd_initmmio();
|
|
/*
|
|
* Call lib/bootblock.c main with BSP, shortcut for APs
|
|
*/
|
|
if (!boot_cpu()) {
|
|
void (*ap_romstage_entry)(void) =
|
|
(void (*)(void))get_ap_entry_ptr();
|
|
|
|
ap_romstage_entry(); /* execution does not return */
|
|
halt();
|
|
}
|
|
|
|
/* TSC cannot be relied upon. Override the TSC value passed in. */
|
|
bootblock_main_with_basetime(timestamp_get());
|
|
}
|
|
|
|
void bootblock_soc_early_init(void)
|
|
{
|
|
bootblock_fch_early_init();
|
|
post_code(0x90);
|
|
}
|
|
|
|
void bootblock_soc_init(void)
|
|
{
|
|
if (CONFIG(AMD_SOC_CONSOLE_UART))
|
|
assert(CONFIG_UART_FOR_CONSOLE >= 0
|
|
&& CONFIG_UART_FOR_CONSOLE <= 1);
|
|
|
|
u32 val = cpuid_eax(1);
|
|
printk(BIOS_DEBUG, "Family_Model: %08x\n", val);
|
|
|
|
bootblock_fch_init();
|
|
}
|