Hannah Williams (hannah.williams@intel.com) just uploaded a new patch set to gerrit, which you can find at https://review.coreboot.org/14316
-gerrit
commit 6dbe522ca456aa0f442d2b090d08cca2900f7022 Author: Hannah Williams hannah.williams@intel.com Date: Tue Mar 22 10:07:21 2016 -0700
soc/apollolake: Set BootMode based on previous sleep state
- fill_power_state makes a copy of the current snapshot of power management registers in CAR variable "power_state" for use in ramstage - migrate_power_state adds CAR variable "power_state" to CBMEM (CBMEM_ID_POWER_STATE) - s3_resume state is updated in romstage_handoff block
Change-Id: I512d6c27a9df3449ef7f4b923e297f6d334d9ed2 Signed-off-by: Hannah Williams hannah.williams@intel.com --- src/soc/intel/apollolake/romstage/romstage.c | 225 +++++++++++++++++++++++++++ 1 file changed, 225 insertions(+)
diff --git a/src/soc/intel/apollolake/romstage/romstage.c b/src/soc/intel/apollolake/romstage/romstage.c new file mode 100644 index 0000000..1e52af8 --- /dev/null +++ b/src/soc/intel/apollolake/romstage/romstage.c @@ -0,0 +1,225 @@ +/* + * This file is part of the coreboot project. + * + * Copyright (C) 2015 Intel Corp. + * (Written by Alexandru Gagniuc alexandrux.gagniuc@intel.com for Intel Corp.) + * (Written by Andrey Petrov andrey.petrov@intel.com for Intel Corp.) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <arch/io.h> +#include <cbfs.h> +#include <cbmem.h> +#include <stddef.h> +#include <string.h> +#include <arch/early_variables.h> +#include <console/console.h> +#include <cpu/x86/msr.h> +#include <device/pci_def.h> +#include <fsp/api.h> +#include <fsp/FspmUpd.h> +#include <fsp/util.h> +#include <device/resource.h> +#include <soc/iomap.h> +#include <soc/pm.h> +#include <soc/romstage.h> +#include <soc/uart.h> +#include <soc/intel/common/mrc_cache.h> +#include <fsp/api.h> +#include <romstage_handoff.h> + +#define FIT_POINTER (0x100000000ULL - 0x40) + +static struct chipset_power_state power_state CAR_GLOBAL; + +/* + * Enables several BARs and devices which are needed for memory init + * - MCH_BASE_ADDR is needed in order to talk to the memory controller + * - PMC_BAR0 and PMC_BAR1 are used by FSP (with the base address hardcoded) + * Once raminit is done, we can safely let the allocator re-assign them + * - HPET is enabled because FSP wants to store a pointer to global data in the + * HPET comparator register + */ +static void soc_early_romstage_init(void) +{ + msr_t msr; + device_t pmc = PCI_DEV(0, 13, 1); + + /* Set MCH base address and enable bit */ + pci_write_config32(PCI_DEV(0, 0, 0), 0x48, MCH_BASE_ADDR | 1); + + /* Set PMC base address */ + pci_write_config32(pmc, PCI_BASE_ADDRESS_0, PMC_BAR0); + pci_write_config32(pmc, PCI_BASE_ADDRESS_1, 0); /* 64-bit BAR */ + pci_write_config32(pmc, PCI_BASE_ADDRESS_2, PMC_BAR1); + pci_write_config32(pmc, PCI_BASE_ADDRESS_3, 0); /* 64-bit BAR */ + + /* PMIO BAR4 was already set in bootblock, hence the COMMAND_IO below */ + pci_write_config32(pmc, PCI_COMMAND, + PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER); + + /* Enable decoding for HPET */ + pci_write_config32(PCI_DEV(0, 13, 0), 0x60, 1<<7); + + /* Work around ACPI timer bug */ + msr.hi = 0x2FBA2E25; + msr.lo = (1<<16) | (ACPI_PMIO_BASE + R_ACPI_PM1_TMR); + wrmsr(0x121, msr); +} + +/* + * Now that FSP is done consuming large amounts of CAR, we can use a much + * larger portion of CAR for the stack. The larger stack is needed for + * decompressing ramstage. It turns out that setting the stack pointer to top + * of CAR gives us the largest uninterrupted stack. + */ +static void *realloc_stack(void) +{ + uintptr_t new_stack = CONFIG_DCACHE_RAM_BASE + CONFIG_DCACHE_RAM_SIZE; + new_stack -= sizeof(size_t); + printk(BIOS_DEBUG, "Placing new stack at 0x%lx\n", new_stack); + return (void *)new_stack; +} + +static void migrate_power_state(int is_recovery) +{ + struct chipset_power_state *ps_cbmem; + struct chipset_power_state *ps_car; + + ps_car = car_get_var_ptr(&power_state); + ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem)); + + if (ps_cbmem == NULL) { + printk(BIOS_DEBUG, "Unable to add power state to cbmem!\n"); + return; + } + memcpy(ps_cbmem, ps_car, sizeof(*ps_cbmem)); +} + +asmlinkage void* romstage_entry(void) +{ + void *hob_list_ptr; + const void *mrc_data; + size_t mrc_data_size; + struct resource fsp_mem; + int prev_sleep_state; + struct romstage_handoff *handoff; + struct chipset_power_state *ps = car_get_var_ptr(&power_state); + + /* Be careful. Bootblock might already have initialized the console */ + if (!IS_ENABLED(CONFIG_BOOTBLOCK_CONSOLE)) { + lpss_console_uart_init(); + console_init(); + } + + printk(BIOS_DEBUG, "Starting romstage...\n"); + + soc_early_romstage_init(); + + prev_sleep_state = fill_power_state(ps); + + fsp_memory_init(&hob_list_ptr); + + fsp_find_reserved_memory(&fsp_mem, hob_list_ptr); + + /* initialize cbmem by adding FSP reserved memory first thing */ + cbmem_initialize_empty_id_size(CBMEM_ID_FSP_RESERVED_MEMORY, + fsp_mem.size); + + migrate_power_state(0); + + /* make sure FSP memory is reserved in cbmem */ + if (fsp_mem.base != (uintptr_t)cbmem_find(CBMEM_ID_FSP_RESERVED_MEMORY)) + die("Failed to accommodate FSP reserved memory request"); + + /* Now that CBMEM is up, save the list so ramstage can use it */ + fsp_save_hob_list(hob_list_ptr); + + /* Save MRC Data to CBMEM */ + if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS) && + (prev_sleep_state != SLEEP_STATE_S3)) + { + if ((mrc_data = fsp_find_nv_storage_data(&mrc_data_size)) && + mrc_cache_stash_data(mrc_data, mrc_data_size) < 0) + printk(BIOS_ERR, "Failed to stash MRC data\n"); + } + /* Create romstage handof information */ + handoff = romstage_handoff_find_or_add(); + if (handoff != NULL) + handoff->s3_resume = (prev_sleep_state == SLEEP_STATE_S3); + else + printk(BIOS_DEBUG, "Romstage handoff structure not added!\n"); + + return realloc_stack(); +} + +asmlinkage void romstage_after_raminit(void) +{ + run_ramstage(); +} + +static void fill_console_params(struct FSPM_UPD *memupd) +{ + if (IS_ENABLED(CONFIG_CONSOLE_SERIAL)) { + memupd->FspmConfig.SerialDebugPortDevice = CONFIG_UART_FOR_CONSOLE; + memupd->FspmConfig.SerialDebugPortType = 2; + memupd->FspmConfig.SerialDebugPortStrideSize = 2; + memupd->FspmConfig.SerialDebugPortAddress = 0; + } else { + memupd->FspmConfig.SerialDebugPortType = 0; + } +} + +void platform_fsp_memory_init_params_cb(struct FSPM_UPD *memupd) +{ + const struct mrc_saved_data *mrc_cache; + struct FSP_M_ARCH_UPD *arch_upd = &memupd->FspmArchUpd; + struct chipset_power_state *ps = car_get_var_ptr(&power_state); + int prev_sleep_state = chipset_prev_sleep_state(ps); + + fill_console_params(memupd); + mainboard_memory_init_params(memupd); + + /* Do NOT let FSP do any GPIO pad configuration */ + memupd->FspmConfig.GpioPadInitTablePtr = NULL; + /* This is somewhere in ASSRAM */ + memupd->FspmConfig.FitTablePtr = read32((void *)FIT_POINTER); + + /* Reserve enough memory under TOLUD to save CBMEM header */ + memupd->FspmArchUpd.BootLoaderTolumSize = cbmem_overhead_size(); + /* TODO: This matches the policy in entry.inc, but should be unified. */ + memupd->FspmArchUpd.StackBase = (void *)CONFIG_FSPM_STACK_BASE; + memupd->FspmArchUpd.StackSize = CONFIG_FSPM_STACK_SIZE; + + arch_upd->Bootmode = FSP_BOOT_WITH_FULL_CONFIGURATION; + + if (IS_ENABLED(CONFIG_CACHE_MRC_SETTINGS)) { + if (!mrc_cache_get_current_with_version(&mrc_cache, 0)) { + /* MRC cache found */ + arch_upd->NvsBufferPtr = (void *)mrc_cache->data; + arch_upd->Bootmode = + prev_sleep_state == SLEEP_STATE_S3 ? + FSP_BOOT_ON_S3_RESUME: + FSP_BOOT_ASSUMING_NO_CONFIGURATION_CHANGES; + printk(BIOS_DEBUG, "MRC cache found, size %x bootmode:%d\n", mrc_cache->size, arch_upd->Bootmode); + } else + printk(BIOS_DEBUG, "MRC cache was not found\n"); + } + +} + +__attribute__ ((weak)) +void mainboard_memory_init_params(struct FSPM_UPD *memupd) +{ + printk(BIOS_DEBUG, "WEAK: %s/%s called\n", __FILE__, __func__); +}