blob: 5968f7379fa79d19a8aa651f29b904a525007592 [file] [log] [blame]
/* SPDX-License-Identifier: GPL-2.0-only */
#include <amdblocks/biosram.h>
#include <acpi/acpi.h>
#include <arch/cpu.h>
#include <arch/romstage.h>
#include <cbmem.h>
#include <console/console.h>
#include <cpu/x86/lapic.h>
#include <halt.h>
#include <program_loading.h>
#include <romstage_handoff.h>
#include <smp/node.h>
#include <string.h>
#include <timestamp.h>
#include <northbridge/amd/agesa/agesa_helper.h>
#include <northbridge/amd/agesa/state_machine.h>
void __weak board_BeforeAgesa(struct sysinfo *cb) { }
static void fill_sysinfo(struct sysinfo *cb)
{
memset(cb, 0, sizeof(*cb));
cb->s3resume = acpi_is_wakeup_s3();
agesa_set_interface(cb);
}
/* APs will enter directly here from bootblock, bypassing verstage
* and potential fallback / normal bootflow detection.
*/
static void ap_romstage_main(void);
static void romstage_main(void)
{
struct postcar_frame pcf;
struct sysinfo romstage_state;
struct sysinfo *cb = &romstage_state;
int cbmem_initted = 0;
fill_sysinfo(cb);
timestamp_add_now(TS_ROMSTAGE_START);
board_BeforeAgesa(cb);
console_init();
printk(BIOS_DEBUG, "APIC %02u: CPU Family_Model = %08x\n",
initial_lapicid(), cpuid_eax(1));
set_ap_entry_ptr(ap_romstage_main);
agesa_execute_state(cb, AMD_INIT_RESET);
agesa_execute_state(cb, AMD_INIT_EARLY);
timestamp_add_now(TS_INITRAM_START);
if (!cb->s3resume)
agesa_execute_state(cb, AMD_INIT_POST);
else
agesa_execute_state(cb, AMD_INIT_RESUME);
timestamp_add_now(TS_INITRAM_END);
/* Work around AGESA setting all memory as WB on normal
* boot path.
*/
fixup_cbmem_to_UC(cb->s3resume);
cbmem_initted = !cbmem_recovery(cb->s3resume);
if (cb->s3resume && !cbmem_initted) {
printk(BIOS_EMERG, "Unable to recover CBMEM\n");
halt();
}
romstage_handoff_init(cb->s3resume);
postcar_frame_init(&pcf, HIGH_ROMSTAGE_STACK_SIZE);
recover_postcar_frame(&pcf, cb->s3resume);
run_postcar_phase(&pcf);
/* We do not return. */
}
static void ap_romstage_main(void)
{
struct sysinfo romstage_state;
struct sysinfo *cb = &romstage_state;
fill_sysinfo(cb);
agesa_execute_state(cb, AMD_INIT_RESET);
agesa_execute_state(cb, AMD_INIT_EARLY);
/* Not reached. */
halt();
}
asmlinkage void car_stage_entry(void)
{
romstage_main();
}
void *cbmem_top_chipset(void)
{
/* Top of CBMEM is at highest usable DRAM address below 4GiB. */
return (void *)restore_top_of_low_cacheable();
}