diff options
Diffstat (limited to 'src/cpu/intel')
-rw-r--r-- | src/cpu/intel/haswell/haswell.h | 11 | ||||
-rw-r--r-- | src/cpu/intel/haswell/romstage.c | 142 |
2 files changed, 149 insertions, 4 deletions
diff --git a/src/cpu/intel/haswell/haswell.h b/src/cpu/intel/haswell/haswell.h index 8d91dbaf02..3ced0c08db 100644 --- a/src/cpu/intel/haswell/haswell.h +++ b/src/cpu/intel/haswell/haswell.h @@ -103,7 +103,16 @@ #ifndef __ROMCC__ #if defined(__PRE_RAM__) -void romstage_main(unsigned long bist); +struct pei_data; +struct rcba_config_instruction; +struct romstage_params { + struct pei_data *pei_data; + const void *gpio_map; + const struct rcba_config_instruction *rcba_config; + unsigned long bist; +}; +void mainboard_romstage_entry(unsigned long bist); +void romstage_common(const struct romstage_params *params); #endif #ifdef __SMM__ diff --git a/src/cpu/intel/haswell/romstage.c b/src/cpu/intel/haswell/romstage.c index f954b91dca..1d00af1c70 100644 --- a/src/cpu/intel/haswell/romstage.c +++ b/src/cpu/intel/haswell/romstage.c @@ -20,9 +20,32 @@ #include <stdint.h> #include <cbmem.h> #include <console/console.h> +#include <arch/cpu.h> +#include <cpu/x86/bist.h> +#include <cpu/x86/msr.h> +#include <lib.h> +#include <timestamp.h> +#include <arch/io.h> +#include <arch/romcc_io.h> +#include <device/pci_def.h> +#include <cpu/x86/lapic.h> +#include <cbmem.h> +#if CONFIG_CHROMEOS +#include <vendorcode/google/chromeos/chromeos.h> +#endif +#include "haswell.h" +#include "northbridge/intel/haswell/haswell.h" +#include "northbridge/intel/haswell/raminit.h" +#include "southbridge/intel/lynxpoint/pch.h" +#include "southbridge/intel/lynxpoint/me.h" + -/* Mainboard needs to supply this symbol. */ -extern void romstage_main(unsigned long bist); +/* The cache-as-ram assembly file calls main() after setting up cache-as-ram. + * main() will then call the mainboards's mainboard_romstage_entry() function. + * That function then calls romstage_common() below. The reason for the back + * and forth is to provide common entry point from cache-as-ram while still + * allowing for code sharing. Because we can't use global variables the stack + * is used for allocations -- thus the need to call back and forth. */ void main(unsigned long bist) { @@ -37,7 +60,7 @@ void main(unsigned long bist) for (i = 0; i < num_guards; i++) stack_base[i] = stack_guard; - romstage_main(bist); + mainboard_romstage_entry(bist); /* Check the stack. */ for (i = 0; i < num_guards; i++) { @@ -51,3 +74,116 @@ void main(unsigned long bist) cbmemc_reinit(); #endif } + +void romstage_common(const struct romstage_params *params) +{ + int boot_mode = 0; + int wake_from_s3; + int cbmem_was_initted; + +#if CONFIG_COLLECT_TIMESTAMPS + tsc_t start_romstage_time; + tsc_t before_dram_time; + tsc_t after_dram_time; + tsc_t base_time = { + .lo = pci_read_config32(PCI_DEV(0, 0x00, 0), 0xdc), + .hi = pci_read_config32(PCI_DEV(0, 0x1f, 2), 0xd0) + }; +#endif + +#if CONFIG_COLLECT_TIMESTAMPS + start_romstage_time = rdtsc(); +#endif + + if (params->bist == 0) + enable_lapic(); + + wake_from_s3 = early_pch_init(params->gpio_map, params->rcba_config); + + /* Halt if there was a built in self test failure */ + report_bist_failure(params->bist); + + /* Perform some early chipset initialization required + * before RAM initialization can work + */ + haswell_early_initialization(HASWELL_MOBILE); + printk(BIOS_DEBUG, "Back from haswell_early_initialization()\n"); + + if (wake_from_s3) { +#if CONFIG_HAVE_ACPI_RESUME + printk(BIOS_DEBUG, "Resume from S3 detected.\n"); + boot_mode = 2; +#else + printk(BIOS_DEBUG, "Resume from S3 detected, but disabled.\n"); +#endif + } + + /* Prepare USB controller early in S3 resume */ + if (boot_mode == 2) + enable_usb_bar(); + + post_code(0x3a); + params->pei_data->boot_mode = boot_mode; +#if CONFIG_COLLECT_TIMESTAMPS + before_dram_time = rdtsc(); +#endif + + report_platform_info(); + + sdram_initialize(params->pei_data); + +#if CONFIG_COLLECT_TIMESTAMPS + after_dram_time = rdtsc(); +#endif + post_code(0x3b); + + intel_early_me_status(); + + quick_ram_check(); + post_code(0x3e); + +#if CONFIG_EARLY_CBMEM_INIT + cbmem_was_initted = !cbmem_initialize(); +#else + cbmem_was_initted = cbmem_reinit((uint64_t) (get_top_of_ram() + - HIGH_MEMORY_SIZE)); +#endif + +#if CONFIG_HAVE_ACPI_RESUME + /* If there is no high memory area, we didn't boot before, so + * this is not a resume. In that case we just create the cbmem toc. + */ + + *(u32 *)CBMEM_BOOT_MODE = 0; + *(u32 *)CBMEM_RESUME_BACKUP = 0; + + if ((boot_mode == 2) && cbmem_was_initted) { + void *resume_backup_memory = cbmem_find(CBMEM_ID_RESUME); + if (resume_backup_memory) { + *(u32 *)CBMEM_BOOT_MODE = boot_mode; + *(u32 *)CBMEM_RESUME_BACKUP = (u32)resume_backup_memory; + } + /* Magic for S3 resume */ + pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, 0xcafed00d); + } else if (boot_mode == 2) { + /* Failed S3 resume, reset to come up cleanly */ + outb(0x6, 0xcf9); + while (1) { + hlt(); + } + } else { + pci_write_config32(PCI_DEV(0, 0x00, 0), SKPAD, 0xcafebabe); + } +#endif + post_code(0x3f); +#if CONFIG_CHROMEOS + init_chromeos(boot_mode); +#endif +#if CONFIG_COLLECT_TIMESTAMPS + timestamp_init(base_time); + timestamp_add(TS_START_ROMSTAGE, start_romstage_time ); + timestamp_add(TS_BEFORE_INITRAM, before_dram_time ); + timestamp_add(TS_AFTER_INITRAM, after_dram_time ); + timestamp_add_now(TS_END_ROMSTAGE); +#endif +} |