diff options
Diffstat (limited to 'src/soc/amd/stoneyridge/bootblock.c')
-rw-r--r-- | src/soc/amd/stoneyridge/bootblock.c | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/soc/amd/stoneyridge/bootblock.c b/src/soc/amd/stoneyridge/bootblock.c new file mode 100644 index 0000000000..4025f80c96 --- /dev/null +++ b/src/soc/amd/stoneyridge/bootblock.c @@ -0,0 +1,104 @@ +/* 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 <soc/pci_devs.h> +#include <soc/cpu.h> +#include <soc/southbridge.h> +#include <amdblocks/psp.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_BASE_ADDR, CONFIG_ROM_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) +{ + /* + * This call (sb_reset_i2c_slaves) was originally early at + * bootblock_c_entry, but had to be moved here. There was an + * unexplained delay in the middle of the i2c transaction when + * we had it in bootblock_c_entry. Moving it to this point + * (or adding delays) fixes the issue. It seems like the processor + * just pauses but we don't know why. + */ + sb_reset_i2c_slaves(); + bootblock_fch_early_init(); + post_code(0x90); +} + +void bootblock_soc_init(void) +{ + if (CONFIG(STONEYRIDGE_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(); + + /* Initialize any early i2c buses. */ + i2c_soc_early_init(); +} |